我正在编写一个名为mapper2
的函数,它将函数应用于两个列表:
mapper2 :: (a-> b -> c) -> [a] -> [b] -> [c]
mapper2 f (x:xs) (y:ys) = (f x y) : (mapper2 f xs ys)
mapper2 _ _ _ = []
我可以编译该函数,但在应用它时会出错:
*Main> mapper2 (\x -> x*2) [2,4] [4,6]
<interactive>:4:1: error:
• Non type-variable argument in the constraint: Num (b -> c)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall b c. (Num (b -> c), Num b) => [c]
有人可以向我解释如何解决这个问题以及错误意味着什么?
答案 0 :(得分:15)
Silvio Mayolo已经涵盖了问题的主要实用部分,因此我将坚持与...相关的技术细节。
错误意味着什么?
首先,错误有点毛茸茸,但您可以首先关注的一件事是Num (b -> c)
位。它表明你在某种程度上试图使用函数类型(b -> c
)作为数字(即Num
的一个实例),这几乎从来没有故意这样做(因为我们通常不使用作为数字的功能)。通常情况下,当这样的事情发生时,这表明某个地方的论点数量不匹配(这就是这里的情况,正如Silvio Mayolo的答案所解释的那样)。也就是说,接下来是对错误如何产生的解释。
mapper2
的第一个参数类型为a -> b -> c
或equivalently,a -> (b -> c)
。当你通过......
(\x -> x * 2) :: Num z => z -> z
...对它,a -> (b -> c)
和Num z => z -> z
匹配(或使用行话,统一),以便第一个z
成为{ {1}},第二个a
变为z
。由于b -> c
两者应该是同一个,z
也变为a
,因此b -> c
的类型专门用于:
(\x -> x * 2)
错误消息(\x -> x * 2) :: Num (b -> c) => (b -> c) -> (b -> c)
指的是如何,与例如Non type-variable argument in the constraint: Num (b -> c)
,约束中有一些不是类型变量的东西。在这种情况下,它是函数类型构造函数Num x
。在启用->
扩展时,正如错误消息所示,允许这样做,没有理由这样做,因为它仍然不是您想要的(您无意将函数用作数字) )。此外,在这种情况下这样做只会导致另一种类型错误。
答案 1 :(得分:8)
查看mapper2
的类型。
mapper2 :: (a -> b -> c) -> [a] -> [b] -> [c]
现在看看你传入的函数的类型。
(\x -> x * 2) :: Num a => a -> a
mapper2
函数需要传入两个参数的函数,但是你的lambda只接受一个参数。