[Haskell-cafe] Why do I have to specify (Monad m) here again?

David House dmhouse at gmail.com
Sun Feb 18 11:29:11 EST 2007

On 18/02/07, David Tolpin <david.tolpin at gmail.com> wrote:
> The following code compiles: is it a bad thing that it does?
> class (Eq a) => Eql a where
>     (=:=) :: a -> a -> Bool
>     x =:= y = x == y
> eql :: Eql a => a -> a -> Bool
> eql x y = x == y

The reason this typechecks:

1) The compiler infers that x and y must have a type which instantiates Eq.
2) Therefore, it infers the type eql :: Eq a => a -> a -> Bool
3) This doesn't match up with the type you specified for eql, though,
so we need to check that your specified type is a specialisation of
the inferred type (see below for a more thorough explanation).
4) It is; if we know that x has a type which instantiates Eql, then we
can prove that this type also instantiates Eq, by the constraint on
the class head of Eql.
5) The program is accepted.

Step 3 may need more explanation. We can use type signatures to
specify a polymorphic type down to a less polymorphic one. For
example, if you wrote:

id x = x

Then the compiler infers id :: a -> a. However, if you only wanted id
to work on Ints, then you could write:

id :: Int -> Int
id x = x

This program would still be accepted, because Int -> Int is less
polymorphic than a -> a, i.e., you can get from a -> a to Int -> Int
by chosing the substitution a = Int. You could also decide that you
only wanted id to work on instances of Show:

id :: Show s => s -> s
id x = x

This'd work, again, because you can get from a -> a to Show s => s ->
s by chosing the substitution a = Show s => s (note that (Show s => s)
-> (Show s => s) is the same as Show s => s -> s). Show s => s -> s is
still a polymorphic type, but it's less polymorphic than a -> a (the
latter is defined over all types, the former only over types that are
instances of Show).


-David House, dmhouse at gmail.com

More information about the Haskell-Cafe mailing list