[Haskell-cafe] Combining computations

Tillmann Rendel rendel at cs.au.dk
Sun May 3 07:33:31 EDT 2009


normally, one uses monads to express and combine computations in the 
same monad. However, you can convert between some monads, e.g. from 
Maybe to List:

   import Data.Maybe (maybeToList)

   > let m1 = Nothing
   > let m2 = [1]
   > let m3 = maybeToList m1 `mplus` m2

   > let m1 = Just 1
   > let m2 = []
   > let m3 = maybeToList m1 `mplus` m2

In fact, you can convert from Maybe to any MonadPlus.

   maybeToMonadPlus Nothing = mzero
   maybeToMonadPlus (Just x) = return x

And you can convert from List to any MonadPlus:

   listToMonadPlus Nothing  = []
   listToMonadPlus (x : xs) = return x `mplus` listToMonadPlus xs

Now you should be able to do:

   m1 = maybeToMonadPlus (Just 1)
   m2 = listtoMonadPlus [2, 3]
   m3 = m1 `mplus` m2 :: Just Int -- Just 1
   m4 = m1 `mplus` m2 :: [Int]    -- [1, 2, 3]

The reason this is possible is that Maybe and List do not support 
additional effects beyond what is common to all MonadPlus instances.

Another option is to never specify which monad your computations are in 
in the first place. Instead, only specify which computational effects 
the monad should support.

   m1 = mzero    :: MonadPlus m => m a
   m2 = return 1 :: (Monad m, Num a) => m a
   m3 = m1 `mplus` m2 `mplus` Just 2 -- Just 1
   m4 = m1 `mplus` m2 `mplus` [2, 3] -- [1, 2, 3]

In this version, m1 and m2 are polymorphic computations, which can be 
used together with List computations, Maybe computations, or any other 
MonadPlus instances. m1 needs MonadPlus, while m2 is happy with any 
Monad instance. This fact is encoded in their type.


More information about the Haskell-Cafe mailing list