Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can you create a value with "Just (+)"?

Currently I'm learning Haskell and are stuck with the instantiation of types to typeclasses. I actually don't understand, why it's possible to create a value of the Maybe a type with Just (+).

The problem why this behaves strange to me is, that the Maybe type is defined as an instance of the Eq typeclass (see Haskell source) and that if you derive an instance for a type, all the fields of the value / data constructors of that type must be also an instance of the Eq typeclass (here).

With this knowledge in mind, the following code shouldn't be compilable or executable, because a function is not a part of the Eq typeclass:

let a = Just (+)
let b = Just (-)

But GHCi actually executes the code without throwing an error message. If you then try to compare these two values (which shouldn't also be possible) the interpreter comes up with the follwing error message:

a == b

<interactive>:24:1: error:
    * No instance for (Eq (Integer -> Integer -> Integer))
        arising from a use of `=='
        (maybe you haven't applied a function to enough arguments?)
    * In the expression: a == b
      In an equation for `it': it = a == b

This problem also occurs if you create your own Maybe a type.

like image 387
Daniel Avatar asked Dec 13 '22 10:12

Daniel


1 Answers

The instance of Eq for Maybe ends up looking like this (that is, deriving (Eq) essentially gets rewritten into this):

instance (Eq a) => Eq (Maybe a) where
    ...

This can be read as if a is a member of Eq, then so is Maybe a. So it's perfectly fine to make a Maybe (Int -> Int) or what have you, it just won't be Eq if its argument isn't.

A more operationally helpful way to think of this, more from the compiler's point of view: to solve a Eq (Maybe a) constraint, it suffices to solve the Eq a constraint. So when we say

a == b

the compiler tries to solve Eq (Maybe (Integer -> Integer -> Integer)). It uses the Maybe instance to reduce the question to Eq (Integer -> Integer -> Integer), and then gives up when there is nothing else it can do. That's why you see the error message complaining about no instance for Eq (Integer -> Integer -> Integer) instead of mentioning Maybe.

like image 141
luqui Avatar answered Jan 03 '23 03:01

luqui