## Wednesday, January 19, 2011

### Corrected Instances for the MonadAttempt class

In my previous post, I outlined the MonadAttempt class that I had created to solve a problem with code generation using a state monad in Haskell. This morning, with a much clearer mind, I was able to create much cleaner instances for the StateT and ErrorT monads:
instance (Monad m, MonadAttempt m) => MonadAttempt (StateT s m) where
attempt a m = do s <- get
lift $attempt a$ do (x, _) <- runStateT m s
return x

attempt a m = lift $attempt a$ do e <- runErrorT m
case e of
Left _ -> return a
Right x -> return x



## Tuesday, January 18, 2011

While working on the code generator for my compiler construction class, I ran across a rather somewhat sticky issue. I am using a state monad to store code as it is generated. This allows me to very quickly build up sequences generated from an AST. However, for conditional instructions, I needed a jump location, which depends on the length of code generated *after* the conditional. There are several ways I could do this, but the solution I invented allows me to generate the code and then 'rewind', knowing the length of the code, and generating the jump instruction. I'm only going to demonstrate instances that I used in my code generator here, as I have not taken the time to write any others. I also haven't spent a lot of time verifying correctness or elegance, so I'd love to hear about any mistakes in the comments.

attempt :: a -> m a -> m a


The MonadAttempt class defines 'attempt', which takes a default value and monadic action, and returns the result of the monadic action without its side effects, or the monadic action returning the default value if the input action fails.

attempt _ m = m


The instance for the Identity monad is trivial. There are no side effects, so we can simply produce the action.

attempt a m = do s <- get
(x, _) <- lift $attempt (a, s)$ runStateT m s
return x

I suppose a more elegant solution would be a do block to extract just the return value from runStateT, but this worked for what I needed. runStateT is used to isolate the side effects, the transformed monad is recursively attempted with a new default value, and the the result is then lifted. But since lift is pure in the transformer (not necessarily the transformed) monad, the state is not updated, and we can extract just the value. (Note that we explicitly get the state and then use it to run the monad.)


attempt a m = do e <- lift $attempt (Right a)$ runErrorT m