我正在编写一个函数mapper2,它将函数应用于两个列表:
mapper2 :: (a-> b -> c) -> [a] -> [b] -> [c]
mapper2 f (x:xs) (y:ys) = (f x y) : (mapper2 f xs ys)
mapper2 _ _ _ = []
Run Code Online (Sandbox Code Playgroud)
我能够编译该函数但在应用它时会出错:
*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]
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释如何解决这个问题以及错误意味着什么?
dup*_*ode 17
Silvio Mayolo已经涵盖了问题的主要部分,因此我将坚持与...相关的技术细节.
这个错误意味着什么?
首先,错误有点毛茸茸,但有一点你可以首先关注的是Num (b -> c)位.它表明你在某种程度上试图使用函数类型(b -> c)作为数字(即一个实例Num),这几乎从来没有故意做过(因为我们通常不使用函数作为数字).通常情况下,当这样的事情发生时,这表明某个地方的论点数量不匹配(这就是这里的情况,正如Silvio Mayolo的答案所解释的那样).也就是说,接下来是对错误如何产生的解释.
的第一个参数mapper2的类型为a -> b -> c或,等价地,a -> (b -> c).当你通过...
(\x -> x * 2) :: Num z => z -> z
Run Code Online (Sandbox Code Playgroud)
...到它,a -> (b -> c)并且Num z => z -> z匹配(或者,使用行话,统一),以便第一个z成为a,第二个z成为b -> c.由于这两种z应该是一样的东西,a变成b -> c为好,等的类型(\x -> x * 2)是专用于:
(\x -> x * 2) :: Num (b -> c) => (b -> c) -> (b -> c)
Run Code Online (Sandbox Code Playgroud)
错误消息Non type-variable argument in the constraint: Num (b -> c)
指的是,与例如Num x,约束内的某些东西不是类型变量不同.在这种情况下,它是函数类型构造函数,->.虽然打开FlexibleContexts扩展程序,正如错误消息所示,允许这样做,但没有理由这样做,因为它仍然不是你想要的(你不打算将函数用作数字).此外,在这种情况下这样做只会导致另一种类型错误.
看看mapper2的类型.
mapper2 :: (a -> b -> c) -> [a] -> [b] -> [c]
Run Code Online (Sandbox Code Playgroud)
现在看看你传入的函数的类型.
(\x -> x * 2) :: Num a => a -> a
Run Code Online (Sandbox Code Playgroud)
该mapper2函数需要两个参数的函数传递的,但你的拉姆达只需要一个参数.
| 归档时间: |
|
| 查看次数: |
11769 次 |
| 最近记录: |