Here are my first proposed improvements. The insertion of type signatures should not be controversial. The use of liftM is perhaps more so, but I think we should try to demonstrate good Haskell usage - and in class, we can show the non-sugared version. The many/many1 recursive relationship is a bit funky, but I think it demonstrates the point that parser combinators are usually extended, rather than restricted, and saves on code duplication.
One thing I have not done is made Parser an instance of Alternative. We should seriously consider this, however, if only because it may "soon" be an error for something to be just an instance of MonadPlus.
Here are my first proposed improvements. The insertion of type signatures should not be controversial. The use of liftM is perhaps more so, but I think we should try to demonstrate good Haskell usage - and in class, we can show the non-sugared version. The many/many1 recursive relationship is a bit funky, but I think it demonstrates the point that parser combinators are usually extended, rather than restricted, and saves on code duplication.
One thing I have not done is made Parser an instance of Alternative. We should seriously consider this, however, if only because it may "soon" be an error for something to be just an instance of MonadPlus.