[[Int]] - > [Int]与乘法

时间:2017-04-19 13:44:35

标签: haskell

我尝试学习Haskell并且我不知道如何创建一个函数,该函数获取列表并将该列表中的每个元素相乘,例如。

ChildClass(speed, direction)

我尝试这样的事情,但它不起作用。如果有人知道该怎么做,对我来说真的很有帮助:

ChildClass([speed, direction])

2 个答案:

答案 0 :(得分:6)

非常简单,你需要map

map product [[2,3],[8,3,2],[2,10,1],[2,2,2,2]]

product函数乘以列表中的所有元素。它包含在Prelude中,默认导入。换句话说,它通常是可用的。

map函数将该函数应用于列表中的每个元素。

答案 1 :(得分:4)

如果您更喜欢只有折叠的解决方案,首先要做一些经验法则:

  • 永远不要使用foldl(“lazy left fold”),除非在非常具体的情况下(在你很长时间了解这些微妙的情况之前,你会遇到这种情况) )。
  • 如果结果是 lazy ,请使用foldr(懒惰的右侧折叠)来解构列表。特别是,如果您的折叠再次生成列表,这通常是正确的选择:foldr将仅按需消耗列表,并且它不会保留对原始头的引用,因此它甚至可以顺利地工作无限列表并避免内存爆炸(实际上,垃圾收集器可以在处理完成之前回收已经处理的列表部分!)
  • 使用foldl'(严格左侧折叠)进行“原子”操作,例如计算列表中所有值的总和。

所以让我们从

开始吧
listOfProductInt :: [[Int]] -> [Int]
-- listOfProductInt [] = [] -- no need for that, folds already handle the empty case.
listOfProductInt lists = foldr _ [] lists

multipleInts :: (Num a) => [a] -> a
multipleInts list1 = foldl' _ 1 list1

GHC会通知你

/tmp/wtmpf-file9164.hs:4:32:
    Found hole ‘_’ with type: [Int] -> [Int] -> [Int]
    Relevant bindings include
      lists :: [[Int]] (bound at /tmp/wtmpf-file9164.hs:4:18)
      listOfProductInt :: [[Int]] -> [Int]
        (bound at /tmp/wtmpf-file9164.hs:4:1)
    In the first argument of ‘foldr’, namely ‘_’

不幸的是,这并不像通常那样具有信息性,因为结果和单个子列表都具有类型[Int]。我将注释类型:

           [Int]   -- the sublist we're focusing on
        -> [Int]   -- the result of the future product-computations yet to be done
        -> [Int]   -- the result at this point of the computation

现在,为了首先处理议程上的子列表,我们有multipleInts。所以,它应该看起来像

listOfProductInt lists = foldr (\l -> _ (multipleInts l)) [] lists

GHC回复

/tmp/wtmpf-file9164.hs:4:39:
    Found hole ‘_’ with type: Int -> [Int] -> [Int]
    Relevant bindings include
      l :: [Int] (bound at /tmp/wtmpf-file9164.hs:4:34)
      lists :: [[Int]] (bound at /tmp/wtmpf-file9164.hs:4:18)
      listOfProductInt :: [[Int]] -> [Int]
        (bound at /tmp/wtmpf-file9164.hs:4:1)
    In the expression: _
    In the expression: _ (multipleInts l)
    In the first argument of ‘foldr’, namely
      ‘(\ l -> _ (multipleInts l))’

您可以将Int -> [Int] -> [Int]a -> [a] -> [a]识别为合作运营商(:)的签名,以及此处所需的内容:

listOfProductInt lists = foldr (\l -> (:) (multipleInts l)) [] lists

或者,使用无点合成,

listOfProductInt = foldr ((:) . multipleInts) []

继续执行multipleInts

/tmp/wtmpf-file9164.hs:7:29:
    Found hole ‘_’ with type: a -> a -> a
    Where: ‘a’ is a rigid type variable bound by
               the type signature for multipleInts :: Num a => [a] -> a
               at /tmp/wtmpf-file9164.hs:6:17
    Relevant bindings include
      list1 :: [a] (bound at /tmp/wtmpf-file9164.hs:7:14)

那么,a -> a -> a a符合Num约束条件?这只是简单的产品操作!

multipleInts list1 = foldl' (*) 1 list1

foldl中只是懒惰,但不在脊椎中。在实践中,这往往会给你两个世界中最糟糕的事情:处理器立即被必须处理整个列表所阻塞,但它实际上并没有进行有用的计算,而只是构建了一堆内存占用懒惰的thunk。