Nested Monads

This is only going to be a quick one. I’ve recently had to embark on a group project at university. The project is building a distributed computation grid on mobile phones. Yes… this probably is a bad idea… but its the task I have been set. I will write a bigger blog post when done!

The project is split into a front end and back end written in C++ and Haskell respectively. Given that I am the only one mad enough to like Haskell, my task is the backend and the parts of the app that interface with the backend (including the task) executer.

But back to the backend. The web is horrible. It is almost exclusively apps and servers sending malformed requests to each other and although I believe weakly types languages to be pure evil, I can see their appeal in this hostile land. But of course weirdly haskell fits into this picture (relatively) nicely. Malformed = Maybe and Input = IO. And this leads me onto why nested monads are the theme of this post. Everything in my app is essentially of the type IO (Maybe a) or Maybe (IO a) so I thought id give you a great function and example that make working with these as easy as possible.

Firstly:

(|>>=|) :: (Monad m1, Monad m2) => m1 (m2 a) -> (a -> m2 b) -> m1 (m2 b)
m |>>=| f = fmap (>>= f) m
infixl 1 |>>=|

This is a beautiful function that allows us to apply a monadic function within a monad. Consider the following example. We have an input to a get request which corresponds to a Haskell type, but it may not have been provided… We get all our GET parameters as an IO list of (String, String)s where the first is the name of the input and the second is the value. Consider the following code:

import Text.Read (readMaybe)

findinput :: [input] -> string -> maybe string
findinput xs s = (safehead $ filter (\(a,_) -> a == s) xs) >>= return . snd
  where safehead []     = nothing
        safehead (x:xs) = just x

readInput s = getInput >>= return . flip findInput s |>>=| readMaybe

This is pretty neat and easy to read in comparison to any fmap or lambda alternative!