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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With