Haskell函数类型不是预期的

时间:2014-06-11 23:04:40

标签: haskell types functional-programming fold

我正在尝试编写一个函数来计算2个列表的内积,即如果列表是[1,2,3]和[4,5,6]那么内积将是(1 x 4) +(2 x 5)+(3 x 6)= 4 + 10 + 18 = 32.

所以我想用zipWith来获取产品,然后foldl将它们与加法相加。因此zipWith应生成[4,10,18],然后foldl应将其加总为32。

所以我写了:

innerprod [] [] = 0
innerprod x y = foldl (+) 0 (zipWith (*) x y)

一切都在编译,但是当我在ghci中运行时:

Prelude ListFuncs> innerprod [1,2,3] [4,5,6]

<interactive>:3:1:
     No instance for (Num
                       ([c0] -> (a0 -> b0 -> a0) -> a0 -> [b0] -> a0))
      arising from a use of `innerprod'
     Possible fix:
      add an instance declaration for
      (Num ([c0] -> (a0 -> b0 -> a0) -> a0 -> [b0] -> a0))
     In the expression: innerprod [1, 2, 3] [4, 5, 6]
     In an equation for `it': it = innerprod [1, 2, 3] [4, 5, 6]

由于错误消息,我尝试制作这样的代码,但在编译时会返回不同的错误:

innerprod :: Num [Int] => (Int -> Int -> Int) -> Int -> [Int] -> Int
innerprod [] [] = 0
innerprod x y = foldl + 0 (zipWith (*) x y)

有谁知道出了什么问题?我希望签名是innerprod :: [Int] -> [Int] -> Int,因为它需要2个int列表并返回一个int。但这也不起作用。感谢您的时间。如果我不应该在这里问这个问题,请告诉我。

1 个答案:

答案 0 :(得分:10)

Num [Int] => (Int -> Int -> Int) -> Int -> [Int] -> Int是一个完整的虚假签名。这意味着:“如果任何整数列表都可以被视为一个数字[??!],我会给你一个特殊版本的折叠”。这不像你想要的内在产品,即Vector -> Vector -> Scalar;在这种情况下Num a => [a] -> [a] -> a。事实上,通过该签名,您的原始定义可以完美地运作:

innerProd :: Num a => [a] -> [a] -> a
innerProd x y = foldl' (+) 0 (zipWith (*) x y)
  

ListFuncs * GT; innerProd [1,2,3] [4,5,6]
  32

我认为你实际尝试了这个。你写的是没有围绕+的parens。

               foldl + 0 (zipWith (*) x y)

现在,这是另一头野兽。这意味着,通过将foldl函数应用于列表的zip来将0 - 函数添加到您获得的函数中......另一个显而易见的事情。请记住,中缀运算符绑定与普通函数应用程序不同,您需要将它们打包在parens中以将它们作为函数参数传递。