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

前端 未结 2 1011
猫巷女王i
猫巷女王i 2021-02-14 08:35

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

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


        
相关标签:
2条回答
  • 2021-02-14 08:57

    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.

    0 讨论(0)
  • 2021-02-14 09:06

    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.

    0 讨论(0)
提交回复
热议问题