[Haskell-cafe] Why is $ right associative instead ofleftassociative?

John Hughes rjmh at cs.chalmers.se
Mon Feb 6 02:39:59 EST 2006

Cale Gibbard wrote:

>That said, I'd *really* like to see monad comprehensions come back,
>since they align better with the view that monads are container types,
>dual to the view that monads are computations, which is supported by
>the do-syntax. This view is actually much easier to teach (in my
>experience). Giving lists a little extra syntax is nice, but giving
>things unnecessarily restrictive types seems to be the point at which
>I'd consider it going too far.

The trouble with monad comprehensions was that it became far too easy to 
write ambiguous programs, even when you thought you were just working 
with lists. Haskell overloading works really nicely *as long as there's 
a judicious mixture of overloaded and non-overloaded functions*, so that 
the overloading actually gets resolved somewhere. Overload too many 
things, and you end up having to insert type annotations in the middle 
of expressions instead, which really isn't nice.

Lists are special, not least because they come very early in a Haskell 
course--or, in my case, in the first ever programming course my students 
have ever taken. Getting error messages about ambiguous overloading when 
they are still trying to understand what comprehension notation means 
(without even the concept of a for-loop to relate it to) is very 
destructive. And this is in the case where the code is otherwise 
type-correct--the kind of error message you would get by trying to 
append a number to a monad comprehension doesn't bear thinking about!

The class system is already something of an obstacle in teaching, 
because you have to mention it in the context of arithmetic (even if you 
tell students always to write monomorphic type signatures, they still 
see classes mentioned in error messages). After all, that is surely why 
Helium doesn't have it. I find classes manageable for arithmetic, even 
if students do take some time to learn to distinguish between a class 
and a type (or a type and a value, for that matter!). But it's a relief 
that list programs, at least, have simple non-overloaded types. List 
functions provide an opportunity to introduce polymorphism in a simple 
context--it's much easier to understand why (++) should have the type 
[a] -> [a] -> [a], than to start talking about MonadPlus m => m a -> m a 
-> m a.

There is a lot to learn in Haskell, especially in the type and class 
system. It's an advantage if you don't have to learn it all at once--if 
you can master lists and list comprehensions without exposure to monads 
(which are a much harder concept). We should never forget that beginners 
have somewhat different needs from expert programmers--and those needs 
are also important. If we want Haskell to be used for first programming 
courses (and it's a big advantage to catch 'em early), then there needs 
to be a learning path into the language that goes quite gently. 
Monomorphic lists help with that.

We did consider more aggressive defaulting to address the ambiguity 
problems with monad comprehensions--defaulting Monad to lists, for 
example, or user-declared defaulting rules--but this introduces yet more 
complexity without really addressing the problem of keeping types simple 
for beginners, so the idea was abandoned.


More information about the Haskell-Cafe mailing list