[Haskell-cafe] Why is $ right associative instead
cgibbard at gmail.com
Mon Feb 6 04:23:12 EST 2006
On 06/02/06, John Hughes <rjmh at cs.chalmers.se> wrote:
> 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.
How about a compiler switch for beginners (maybe with an included
script that adds it to the command line) that turns off a bunch of the
more complex issues involved, and uses a beginner's version of the
Prelude? Helium exists as well, which is a simplified version of
Haskell for beginners, without even typeclasses. It has very careful
and detailed error messages.
Having monad comprehensions actually helps with another newbie
problem, albeit one which is a little farther along the garden path --
learning about monads.
Defaulting monad comprehensions is probably a good idea. List
comprehensions are probably the most common case anyway, just because
lists are the most common container type. :) This also further helps
in introducing monads as generalisations of lists.
If extensions to the language get standardised, I'd be fine with
having monad comprehensions among them. Adding an extension
declaration or compiler switch to any module using them wouldn't be so
bad either, though I'd really like them in the actual language. I'd
also want to include the usual changes to the prelude. The situation
with map I find especially grating. Having two versions of common
functions is one thing, but 3 is getting out there! :) Is explaining
Functor really that hard? It's just container types with a way to
apply a function to all of their elements. :)
I don't think it should be necessary to completely rule out useful
features because they might be difficult to newcomers. There should
always be ways to turn things off, and construct a simpler language
for new users. Dr. Scheme seems to take this approach, and has a
pretty fine gradation of languages for leading users from their first
steps into the finer points of Scheme. (I'm not completely sure how
well Dr. Scheme works in practice as I haven't used it a whole lot
myself, but the idea is great, and it certainly looks quite nice.)
Also, it seems that classes are one of the first things one has to
teach now anyway, as they're bound to come up in error messages in any
actual programs you try to write. When teaching my friend, I taught
the basics of classes along with types in the first and second lesson
(including how to define them) and presented various values and
functions as examples.
Perhaps certain error messages would still be confusing after a basic
intro to classes, but I think that improving error messages would help
quite a lot here. :) GHC's ability to suggest common fixes is fairly
useful (though occasionally misleading).
An automatic (interactive?) glossary for terms like 'unresolved
overloading' would be quite good. It would also be nice to offer links
in error messages to the Haskell wiki, where users could discuss
common reasons and fixes for a given error.
More information about the Haskell-Cafe