Haskell映射函数的约束错误中的非类型变量参数

时间:2016-11-30 17:22:49

标签: haskell

我正在编写一个名为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]

有人可以向我解释如何解决这个问题以及错误意味着什么?

2 个答案:

答案 0 :(得分:15)

Silvio Mayolo已经涵盖了问题的主要实用部分,因此我将坚持与...相关的技术细节。

  

错误意味着什么?

首先,错误有点毛茸茸,但您可以首先关注的一件事是Num (b -> c)位。它表明你在某种程度上试图使用函数类型(b -> c)作为数字(即Num的一个实例),这几乎从来没有故意这样做(因为我们通常不使用作为数字的功能)。通常情况下,当这样的事情发生时,这表明某个地方的论点数量不匹配(这就是这里的情况,正如Silvio Mayolo的答案所解释的那样)。也就是说,接下来是对错误如何产生的解释。

mapper2的第一个参数类型为a -> b -> cequivalentlya -> (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只接受一个参数。