
I find it's good for the soul to remember what the do notation is doing for us.
Also I'm with Einstein on "You do not really understand something unless you can explain it to your grandmother" :)
Personally I think (in this instance) your three 'Parser a' functions read nicer as:
primary = (identifier >>= (return . PrimaryIdentifier)) <|> (stringLiteral >>= (return . PrimaryLiteral)) identifier = (many1 letter) >>= (return . Identifier) stringLiteral = (char '\'') >> (manyTill anyChar (char '\'')) >>= (return . StringLiteral) Thanks, I tried to do this, but got stuck. I was missing the 'return .'
Looking at them in this form Tomek's point should seem clear now, especially when we look at the type signature for liftM:
liftM :: Monad m => (a1 -> r) -> m a1 -> m r
So we can (marginally) shorten down to:
primary = (liftM PrimaryIdentifier identifier) <|> (liftM PrimaryLiteral stringLiteral) identifier = liftM Identifier (many1 letter) stringLiteral = liftM StringLiteral ((char '\'') >> (manyTill anyChar (char '\''))) I had initially tried following the types through of liftM as I didn't get Tomek's approach straight away. It did make a bit of sense, but with
Dave Tapley wrote: the extra step of getting rid of the do notation made it clearer.
You might like: http://syntaxfree.wordpress.com/2006/12/12/do-notation-considered-harmful/
Thanks for the link. I have been trying to avoid do notation, as I think it helps my understanding of what's really going on with monads. In this case though, I got stuck when I left out the 'return .' and resorted to do notation because it worked :( Levi lstephen.wordpress.com