Non type-variable argument in the constraint error on Haskell map function

為{幸葍}努か 提交于 2020-08-22 05:11:25

问题


I am writing a function called mapper2 that applies a function to two lists:

mapper2 :: (a-> b -> c) -> [a] -> [b] -> [c]
mapper2 f (x:xs) (y:ys) = (f x y) : (mapper2 f xs ys)
mapper2 _ _ _ = []

I am able to compile the function but get an error when I apply it:

*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]

Can someone explain to me how to fix this and what the error means?


回答1:


Look at mapper2's type.

mapper2 :: (a -> b -> c) -> [a] -> [b] -> [c]

Now look at the type of the function you're passing in.

(\x -> x * 2) :: Num a => a -> a

The mapper2 function expects a function of two arguments to be passed in, but your lambda only takes one argument.




回答2:


Silvio Mayolo has covered the main, practical part of the question, so I will stick to the technical details related to...

what the error means?

To begin with, the error is a bit hairy, but one thing that you can focus on at first is the Num (b -> c) bit. It indicates that you are somehow trying to use a function type (b -> c) as a number (i.e. an instance of Num), which is something that is almost never done intentionally (as we usually do not use functions as numbers). More often than not, when such things happen it is a sign that there is a mismatch in the number of arguments somewhere (which is the case here, as explained by Silvio Mayolo's answer). That said, what follows is an explanation of how the error comes about.

The first argument of mapper2 has type a -> b -> c or, equivalently, a -> (b -> c). When you pass...

(\x -> x * 2) :: Num z => z -> z

... to it, a -> (b -> c) and Num z => z -> z are matched (or, using the jargon, unified), so that the first z becomes a and the second z becomes b -> c. Since both z are supposed to be the same thing, a becomes b -> c as well, and so the type of (\x -> x * 2) is specialised to:

(\x -> x * 2) :: Num (b -> c) => (b -> c) -> (b -> c)

The error message Non type-variable argument in the constraint: Num (b -> c) refers to how, unlike in e.g. Num x, there is something within the constraint that is not a type variable. In this case, it is function type constructor, ->. While turning on the FlexibleContexts extension, as the error message suggests, would allow that, there is no reason to do so here, as it still wouldn't be what you want (you have no intention of using functions as numbers). Furthermore, doing so in this case would just lead to another type error.



来源:https://stackoverflow.com/questions/40894475/non-type-variable-argument-in-the-constraint-error-on-haskell-map-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!