Yet Another Haskell Tutorial/Monads/Solutions

Common Monads
The first law is:  &equiv;. In the case of, we get:

return a >>= f ==> Just a   >>= \x -> f x ==>  (\x -> f x) a ==>  f a The second law is:   &equiv;. Here, we get:

f >>= return ==> f >>= \x -> return x ==>  f >>= \x -> Just x At this point, there are two cases depending on whether   is  or not. In the first case, we get:

==> Nothing >>= \x -> Just x ==>  Nothing ==> f In the second case,   is. Then, we get:

==> Just a >>= \x -> Just x ==>  (\x -> Just x) a ==>  Just a ==>  f And the second law is shown. The third law states:  &equiv;.

If  is , then the left-hand-side clearly reduces to .  The right-hand-side reduces to   which in turn reduces to, so they are the same.

Suppose  is. Then the LHS reduces to and the RHS reduces to   which in turn reduces to, so these two are the same.

The idea is that we wish to use the  constructor to represent errors on the  constructor to represent successes. This leads to an instance declaration like:

instance Monad (Either String) where return x     = Right x    Left  s >>= _ = Left s    Right x >>= f = f x    fail  s       = Left s If we try to use this monad to do search, we get:

which is exactly what we want.

MonadPlus
The order to  essentially determins the search order. When the recursive call to  comes first, we are doing depth-first search. When the recursive call to  comes first, we are doing breadth-first search. Thus, using the list monad, we expect the solutions to come in the other order:

Just as we expected.

Monad Transformers
This is a very difficult problem; if you found that you were stuck immediately, please just read as much of this solution as you need to try it yourself.

First, we need to define a list transformer monad. This looks like:

newtype ListT m e = ListT { unListT :: m [e] } The  constructor simply wraps a monadic action (in monad ) which returns a list.

We now need to make this a monad:

instance Monad m => Monad (ListT m) where return x = ListT (return [x]) fail  s = ListT (return [] ) ListT m >>= k = ListT $ do     l  <- m      l' <- mapM (unListT . k) l      return (concat l')

Here, success is designated by a monadic action which returns a singleton list. Failure (like in the standard list monad) is represented by an empty list: of course, it's actually an empty list returned from the enclosed monad. Binding happens essentially by running the action which will result in a list. This has type . We now need to apply   to each of these elements (which will result in something of type .  We need to get rid of the  s around this (by using  ) and then concatenate them to make a single list.

Now, we need to make it an instance of

instance Monad m => MonadPlus (ListT m) where mzero = ListT (return []) ListT m1 `mplus` ListT m2 = ListT $ do     l1 <- m1      l2 <- m2      return (l1 ++ l2)

Here, the zero element is a monadic action which returns an empty list. Addition is done by executing both actions and then concatenating the results.

Finally, we need to make it an instance of :

instance MonadTrans ListT where lift x = ListT (do a <- x; return [a]) Lifting an action into  simply involves running it and getting the value (in this case, ) out and then returning the singleton list.

Once we have all this together, writing  is fairly straightforward:

searchAll6 g@(Graph vl el) src dst | src == dst = do     lift $ putStrLn $ "Exploring " ++ show src ++ " -> " ++ show dst return [src] | otherwise = do      lift $ putStrLn $ "Exploring " ++ show src ++ " -> " ++ show dst search' el where search' [] = mzero search' ((u,v,_):es) | src == u = (do path <- searchAll6 g v dst             return (u:path)) `mplus` search' es       | otherwise = search' es The only change (besides changing the recursive call to call  instead of  ) here is that we call with appropriate arguments, lifted into the monad.

If we look at the type of, we see that the result (i.e., after applying a graph and two ints) has type. In theory, we could use this with any appropriate monad transformer; in our case, we want to use . Thus, we can run this by:

This is precisely what we were looking for. This exercise is actually simpler than the previous one. All we need to do is incorporate the calls to  and   into and add an extra lift to the IO calls. This extra lift is required because now we're stacking two transformers on top of IO instead of just one.

searchAll7 g@(Graph vl el) src dst | src == dst = do     lift $ lift $ putStrLn $ "Exploring " ++ show src ++ " -> " ++ show dst visited <- getT putT (src:visited) return [src] | otherwise = do      lift $ lift $ putStrLn $ "Exploring " ++ show src ++ " -> " ++ show dst visited <- getT putT (src:visited) if src `elem` visited then mzero else search' el where search' [] = mzero search' ((u,v,_):es) | src == u = (do path <- searchAll7 g v dst             return (u:path)) `mplus` search' es       | otherwise = search' es The type of this has grown significantly. After applying the graph and two ints, this has type.

Essentially this means that we've got something that's a state transformer wrapped on top of some other arbitrary transformer which itself sits on top of. In our case,  is going to be. Thus, we run this beast by saying:

And it works, even on.

A Simple Parsing Monad
First we write a function  which will parse out whitespaces:

spaces :: Parser spaces = many (matchChar isSpace) >> return Now, using this, we simply sprinkle calls to  through to get :

intListSpace :: Parser [Int] intListSpace = do char '[' spaces intList' `mplus` (char ']' >> return []) where intList' = do           i <- int spaces r <- (char ',' >> spaces >> intList') `mplus` (char ']' >> return []) return (i:r) We can test that this works:

=== Parsec === We do this by replacing the state functions with push and pop functions as follows:

parseValueLet2 :: CharParser (FiniteMap Char [Int]) Int parseValueLet2 = choice [ int , do string "let " c <- letter char '=' e <- parseValueLet2 string " in " pushBinding c e      v <- parseValueLet2 popBinding c      return v , do c  <- letter fm <- getState case lookupFM fm c of        Nothing    -> unexpected ("variable " ++                                   show c ++                                   " unbound") Just (i:_) -> return i, between (char '(') (char ')') $ do      e1 <- parseValueLet2 op <- oneOf "+*" e2 <- parseValueLet2 case op of       '+' -> return (e1 + e2) '*' -> return (e1 * e2) ] where pushBinding c v = do     fm <- getState case lookupFM fm c of       Nothing -> setState (addToFM fm c [v]) Just l -> setState (addToFM fm c (v:l)) popBinding c = do     fm <- getState case lookupFM fm c of       Just [_]   -> setState (delFromFM fm c)        Just (_:l) -> setState (addToFM fm c l)

The primary difference here is that instead of calling , we use two local functions,  and . The   function takes a variable name and a value and adds the value onto the head of the list pointed to in the state. The  function looks at the value and if there is only one element on the stack, it completely removes the stack from the ; otherwise it just removes the first element. This means that if something is in the , the stack is never empty.

This enables us to modify only slightly the usage case; this time, we simply take the top element off the stack when we need to inspect the value of a variable.

We can test that this works: