RE monads: for me, I didn’t grok them until I built one myself. A really easy one to start with is to make your own randomness monad. And once you have that, try to make it polymorphic with respect to the random number generator. You’ll probably only need a dozen or two lines to do it, but it’s a nice exercise if you’re grappling with monads.
Also, I highly recommend Imperative functional programming, which is the paper where Simon Peyton Jones and Phil Wadler introduced the IO monad. It is very readable if you have some basic experience with functional programming. The paper very nicely walks you through the design of the IO monad.
RE parsing: Parsing with monads is a lot of fun and also something worth trying out if you haven’t before. However, I found that the documentation for parsec difficult to read, partially due to the API being spread out over so many modules. It’s unfortunate that Haddock exposes the underlying module hierarchy instead of just giving us a nice clear public API. (e.g., Text.Parsec re-exports a whole mess of sub-modules, but we still need to dive into each one.) I haven’t tried attoparsec yet.