Monday, March 19, 2012

LYAH - Chapter 12 A Fistful of Monads


A Fistful of Monads
·         Monads are a natural extension of applicative functors and with them we're concerned with this: if you have a value with a context, m a, how do you apply to it a function that takes a normal a and returns a value with a context?
·         How do you apply a function of type a -> m b to a value of type m a?
  1. (>>=) :: (Monad m) => m a -> (a -> m b) -> m b  
·         If we have a fancy value and a function that takes a normal value but returns a fancy value, how do we feed that fancy value into the function? 
·         We write m a instead of f a because the m stands for Monad, but monads are just applicative functors that support >>=.
·         >>= is pronounced as bind.

Maybe Monad
·         >>= would take a Maybe a value and a function of type a -> Maybe b and somehow apply the function to the Maybe a. To figure out how it does that, we can use the intuition that we have from Maybe being an applicative functor. Let's say that we have a function \x -> Just (x+1). It takes a number, adds 1 to it and wraps it in a Just:
  1. ghci> (\x -> Just (x+1)) 1  
  2. Just 2  
  3. ghci> (\x -> Just (x+1)) 100  
  4. Just 101  
·         If we feed it 1, it evaluates to Just 2. If we give it the number 100, the result is Just 101.
·         How do we feed a Maybe value to this function?
·         Instead of calling it >>=, let's call it applyMaybe for now. It takes a Maybe a and a function that returns a Maybe b and manages to apply that function to the Maybe a.
  1. applyMaybe :: Maybe a -> (a -> Maybe b) -> Maybe b  
  2. applyMaybe Nothing f  = Nothing  
  3. applyMaybe (Just x) f = f x  
  1. ghci> Just 3 `applyMaybe` \x -> Just (x+1)  
  2. Just 4  
  3. ghci> Just "smile" `applyMaybe` \x -> Just (x ++ " :)")  
  4. Just "smile :)"  
  5. ghci> Nothing `applyMaybe` \x -> Just (x+1)  
  6. Nothing  
  7. ghci> Nothing `applyMaybe` \x -> Just (x ++ " :)")  
  8. Nothing  
  9. ghci> Just 3 `applyMaybe` \x -> if x > 2 then Just x else Nothing  
  10. Just 3  
  11. ghci> Just 1 `applyMaybe` \x -> if x > 2 then Just x else Nothing  
  12. Nothing  
Monad type class
  1. class Monad m where  
  2.     return :: a -> m a  
  3.   
  4.     (>>=) :: m a -> (a -> m b) -> m b  
  5.   
  6.     (>>) :: m a -> m b -> m b  
  7.     x >> y = x >>= \_ -> y  
  8.   
  9.     fail :: String -> m a  
  10.     fail msg = error msg  
·         There should be a class constraint in there along the lines of class (Applicative m) = > Monad m where so that a type has to be an applicative functor first before it can be made a monad but when Haskell was made, it hadn't occurred to people that applicative functors are a good fit for Haskell so they weren't in there. But rest assured, every monad is an applicative functor, even if the Monad class declaration doesn't say so.
·         The first function that the Monad type class defines is return.
·         It's the same as pure, only with a different name.
·         It takes a value and puts it in a minimal default context that still holds that value. In other words, it takes something and wraps it in a monad.
·         It always does the same thing as the pure function from the Applicative type class, which means we're already acquainted with return.
·         We already used return when doing I/O.  We used it to take a value and make a bogus I/O action that does nothing but yield that value.
·         For Maybe it takes a value and wraps it in a Just.
·         >>=, or bind.
·         It's like function application, only instead of taking a normal value and feeding it to a normal function, it takes a monadic value (that is, a value with a context) and feeds it to a function that takes a normal value but returns a monadic value.
·         >> - we pretty much never implement it when making Monad instances.
·         fail. We never use it explicitly in our code. Instead, it's used by Haskell to enable failure in a special syntactic construct for monads that we'll meet later.

Maybe Monad Example
  1. instance Monad Maybe where  
  2.     return x = Just x  
  3.     Nothing >>= f = Nothing  
  4.     Just x >>=  = f x  
  5.     fail _ = Nothing  
·         return is the same as pure
·         >>=  is the same as our applyMaybe.
  1. ghci> return "WHAT" :: Maybe String  
  2. Just "WHAT"  
  3. ghci> Just 9 >>= \x -> return (x*10)  
  4. Just 90  
  5. ghci> Nothing >>= \x -> return (x*10)  
  6. Nothing  
Walk the line Example
·         Let's see how we can use >>= repeatedly to handle computations of several Maybe a values.
·         Tightrope walker, birds keep landing on his balancing pole!
·         Keeps his balance if the number of birds on the left side of the pole and on the right side of the pole is within three.
·         Represent the pole with a simple pair of integers: (number of birds on the left side, number of birds on the right side)
  1. type Birds = Int  
  2. type Pole = (Birds,Birds) 

  1. landLeft :: Birds -> Pole -> Maybe Pole  
  2. landLeft n (left,right)  
  3.     | abs ((left + n) - right) < 4 = Just (left + n, right)  
  4.     | otherwise                    = Nothing  
  5.   
  6. landRight :: Birds -> Pole -> Maybe Pole  
  7. landRight n (left,right)  
  8.     | abs (left - (right + n)) < 4 = Just (left, right + n)  
  9.     | otherwise                    = Nothing 

  1. ghci> landLeft 2 (0,0)  
  2. Just (2,0)  
  3. ghci> landLeft 10 (0,3)  
  4. Nothing  
·         We need a way of taking a Maybe Pole and feeding it to a function that takes a Pole and returns a Maybe Pole. Luckily, we have >>=, which does just that for Maybe. Let's give it a go:
  1. ghci> landRight 1 (0,0) >>= landLeft 2  
  2. Just (2,1)  
  1. ghci> Nothing >>= landLeft 2  
  2. Nothing  
·         We can now chain landings that may fail because >>= allows us to feed a monadic value to a function that takes a normal one.
  1. ghci> return (0,0) >>= landRight 2 >>= landLeft 2 >>= landRight 2  
  2. Just (2,4)  
  1. ghci> return (0,0) >>= landLeft 1 >>= landRight 4 >>= landLeft (-1) >>= landRight (-2)  
  2. Nothing  
·         We couldn't have achieved this by just using Maybe as an applicative.
·         If you try it, you'll get stuck, because applicative functors don't allow for the applicative values to interact with each other very much.
·         They can, at best, be used as parameters to a function by using the applicative style.
·         The applicative operators will fetch their results and feed them to the function in a manner appropriate for each applicative and then put the final applicative value together, but there isn't that much interaction going on between them.
·         Here, however, each step relies on the previous one's result.
·         On every landing, the possible result from the previous one is examined and the pole is checked for balance.
·         This determines whether the landing will succeed or fail.
·         banana = a function that ignores the current number of birds on the balancing pole and just makes Pierre slip and fall.
  1. banana :: Pole -> Maybe Pole  
  2. banana _ = Nothing  
  1. ghci> return (0,0) >>= landLeft 1 >>= banana >>= landRight 1  
  2. Nothing  
·         Instead of making functions that ignore their input and just return a predetermined monadic value, we can use the >> function, whose default implementation is this:
  1. (>>) :: (Monad m) => m a -> m b -> m b  
  2. m >> n = m >>= \_ -> n  
  1. ghci> Nothing >> Just 3  
  2. Nothing  
  3. ghci> Just 3 >> Just 4  
  4. Just 4  
  5. ghci> Just 3 >> Nothing  
  6. Nothing  
  1. ghci> return (0,0) >>= landLeft 1 >> Nothing >>= landRight 1  
  2. Nothing  
·         Here's how a series of bird landings would look like without monadic bindings:
  1. routine :: Maybe Pole  
  2. routine = case landLeft 1 (0,0of  
  3.     Nothing -> Nothing  
  4.     Just pole1 -> case landRight 4 pole1 of   
  5.         Nothing -> Nothing  
  6.         Just pole2 -> case landLeft 2 pole2 of  
  7.             Nothing -> Nothing  
  8.             Just pole3 -> landLeft 1 pole3  
·         The Maybe monad saves us a lot of time when we have to successively do computations that are based on computations that might have failed.
do notation
·         Monads in Haskell are so useful that they got their own special syntax called do notation.
·         do notation isn't just for IO, but can be used for any monad.
·         Its principle is still the same: gluing together monadic values in sequence. We're going to take a look at how do notation works and why it's useful.
  1. ghci> Just 3 >>= (\x -> Just (show x ++ "!"))  
  2. Just "3!"  
  1. ghci> Just 3 >>= (\x -> Just "!" >>= (\y -> Just (show x ++ y)))  
  2. Just "3!"  
·         In the outermost lambda, we feed Just "!" to the lambda \y -> Just (show x ++ y). Inside this lambda, the y becomes "!"x is still 3 because we got it from the outer lambda.
  1. ghci> Nothing >>= (\x -> Just "!" >>= (\y -> Just (show x ++ y)))  
  2. Nothing  
  3. ghci> Just 3 >>= (\x -> Nothing >>= (\y -> Just (show x ++ y)))  
  4. Nothing  
  5. ghci> Just 3 >>= (\x -> Just "!" >>= (\y -> Nothing))  
  6. Nothing 

  1. foo :: Maybe String  
  2. foo = Just 3   >>= (\x -> 
  3.       Just "!" >>= (\y -> 
  4.       Just (show x ++ y)))  
·         To save us from writing all these annoying lambdas, Haskell gives us do notation.
  1. foo :: Maybe String  
  2. foo = do  
  3.     x <- Just 3  
  4.     y <- Just "!"  
  5.     Just (show x ++ y)  
·         We've gained the ability to temporarily extract things from Maybe values without having to check if the Maybe values are Just values or Nothing values at every step.
·         do expressions are just different syntax for chaining monadic values.
·         In a do expression, every line is a monadic value. To inspect its result, we use<-. If we have a Maybe String and we bind it with <- to a variable, that variable will be a String, just like when we used >>= to feed monadic values to lambdas. The last monadic value in a do expression, like Just (show x ++ y) here, can't be used with <- to bind its result, because that wouldn't make sense if we translated the do expression back to a chain of >>= applications. Rather, its result is the result of the whole glued up monadic value, taking into account the possible failure of any of the previous ones.
·         For instance, examine the following line:
  1. ghci> Just 9 >>= (\x -> Just (x > 8))  
  2. Just True  
·         Because the left parameter of >>= is a Just value, the lambda is applied to 9 and the result is a Just True. If we rewrite this in do notation, we get:
  1. marySue :: Maybe Bool  
  2. marySue = do   
  3.     x <- Just 9  
  4.     Just (x > 8)  
·         If we compare these two, it's easy to see why the result of the whole monadic value is the result of the last monadic value in thedo expression with all the previous ones chained into it.
·         Our tightwalker's routine can also be expressed with do notation. landLeft and landRight take a number of birds and a pole and produce a pole wrapped in a Just, unless the tightwalker slips, in which case a Nothing is produced. We used>>= to chain successive steps because each one relied on the previous one and each one had an added context of possible failure. Here's two birds landing on the left side, then two birds landing on the right and then one bird landing on the left:
  1. routine :: Maybe Pole  
  2. routine = do  
  3.     start <- return (0,0)  
  4.     first <- landLeft 2 start  
  5.     second <- landRight 2 first  
  6.     landLeft 1 second  
·         Let's see if he succeeds:
  1. ghci> routine  
  2. Just (3,2)  
·         He does! Great. When we were doing these routines by explicitly writing >>=, we usually said something likereturn (0,0) >>= landLeft 2, because landLeft 2 is a function that returns a Maybe value. With do expressions however, each line must feature a monadic value. So we explicitly pass the previous Pole to the landLeft landRightfunctions. If we examined the variables to which we bound our Maybe values, start would be (0,0)first would be(2,0) and so on.
·         Because do expressions are written line by line, they may look like imperative code to some people. But the thing is, they're just sequential, as each value in each line relies on the result of the previous ones, along with their contexts (in this case, whether they succeeded or failed).
·         Again, let's take a look at what this piece of code would look like if we hadn't used the monadic aspects of Maybe:
  1. routine :: Maybe Pole  
  2. routine =   
  3.     case Just (0,0of   
  4.         Nothing -> Nothing  
  5.         Just start -> case landLeft 2 start of  
  6.             Nothing -> Nothing  
  7.             Just first -> case landRight 2 first of  
  8.                 Nothing -> Nothing  
  9.                 Just second -> landLeft 1 second  
·         See how in the case of success, the tuple inside Just (0,0) becomes start, the result of landLeft 2 start becomesfirst, etc.
·         If we want to throw the Pierre a banana peel in do notation, we can do the following:
  1. routine :: Maybe Pole  
  2. routine = do  
  3.     start <- return (0,0)  
  4.     first <- landLeft 2 start  
  5.     Nothing  
  6.     second <- landRight 2 first  
  7.     landLeft 1 second  
·         When we write a line in do notation without binding the monadic value with <-, it's just like putting >> after the monadic value whose result we want to ignore. We sequence the monadic value but we ignore its result because we don't care what it is and it's prettier than writing _ <- Nothing, which is equivalent to the above.
·         When to use do notation and when to explicitly use >>= is up to you. I think this example lends itself to explicitly writing >>=because each step relies specifically on the result of the previous one. With do notation, we had to specifically write on which pole the birds are landing, but every time we used that came directly before. But still, it gave us some insight into do notation.
·         In do notation, when we bind monadic values to names, we can utilize pattern matching, just like in let expressions and function parameters. Here's an example of pattern matching in a do expression:
  1. justH :: Maybe Char  
  2. justH = do  
  3.     (x:xs) <- Just "hello"  
  4.     return x  
·         We use pattern matching to get the first character of the string "hello" and then we present it as the result. So justHevaluates to Just 'h'.
·         What if this pattern matching were to fail? When matching on a pattern in a function fails, the next pattern is matched. If the matching falls through all the patterns for a given function, an error is thrown and our program crashes. On the other hand, failed pattern matching in let expressions results in an error being produced right away, because the mechanism of falling through patterns isn't present in let expressions. When pattern matching fails in a do expression, the fail function is called. It's part of the Monad type class and it enables failed pattern matching to result in a failure in the context of the current monad instead of making our program crash. Its default implementation is this:
  1. fail :: (Monad m) => String -> m a  
  2. fail msg = error msg  
·         So by default it does make our program crash, but monads that incorporate a context of possible failure (like Maybe) usually implement it on their own. For Maybe, its implemented like so:
  1. fail _ = Nothing  
·         It ignores the error message and makes a Nothing. So when pattern matching fails in a Maybe value that's written in donotation, the whole value results in a Nothing. This is preferable to having our program crash. Here's a do expression with a pattern that's bound to fail:
  1. wopwop :: Maybe Char  
  2. wopwop = do  
  3.     (x:xs) <- Just ""  
  4.     return x  
·         The pattern matching fails, so the effect is the same as if the whole line with the pattern was replaced with a Nothing. Let's try this out:
  1. ghci> wopwop  
  2. Nothing  
·         The failed pattern matching has caused a failure within the context of our monad instead of causing a program-wide failure, which is pretty neat.
List monad
·         So far, we've seen how Maybe values can be viewed as values with a failure context and how we can incorporate failure handling into our code by using >>= to feed them to functions. In this section, we're going to take a look at how to use the monadic aspects of lists to bring non-determinism into our code in a clear and readable manner.
·         We've already talked about how lists represent non-deterministic values when they're used as applicatives. A value like 5 is deterministic. It has only one result and we know exactly what it is. On the other hand, a value like [3,8,9] contains several results, so we can view it as one value that is actually many values at the same time. Using lists as applicative functors showcases this non-determinism nicely:
  1. ghci> (*) <$> [1,2,3] <*> [10,100,1000]  
  2. [10,100,1000,20,200,2000,30,300,3000]  
·         All the possible combinations of multiplying elements from the left list with elements from the right list are included in the resulting list. When dealing with non-determinism, there are many choices that we can make, so we just try all of them, and so the result is a non-deterministic value as well, only it has many more results.
·         This context of non-determinism translates to monads very nicely. Let's go ahead and see what the Monad instance for lists looks like:
  1. instance Monad [] where  
  2.     return x = [x]  
  3.     xs >>= f = concat (map f xs)  
  4.     fail _ = []  
·         return does the same thing as pure, so we should already be familiar with return for lists. It takes a value and puts it in a minimal default context that still yields that value. In other words, it makes a list that has only that one value as its result. This is useful for when we want to just wrap a normal value into a list so that it can interact with non-deterministic values.
·         To understand how >>= works for lists, it's best if we take a look at it in action to gain some intuition first. >>= is about taking a value with a context (a monadic value) and feeding it to a function that takes a normal value and returns one that has context. If that function just produced a normal value instead of one with a context, >>= wouldn't be so useful because after one use, the context would be lost. Anyway, let's try feeding a non-deterministic value to a function:
  1. ghci> [3,4,5] >>= \x -> [x,-x]  
  2. [3,-3,4,-4,5,-5]  
·         When we used >>= with Maybe, the monadic value was fed into the function while taking care of possible failures. Here, it takes care of non-determinism for us. [3,4,5] is a non-deterministic value and we feed it into a function that returns a non-deterministic value as well. The result is also non-deterministic, and it features all the possible results of taking elements from the list [3,4,5] and passing them to the function \x -> [x,-x]. This function takes a number and produces two results: one negated and one that's unchanged. So when we use >>= to feed this list to the function, every number is negated and also kept unchanged. The x from the lambda takes on every value from the list that's fed to it.
·         To see how this is achieved, we can just follow the implementation. First, we start off with the list [3,4,5]. Then, we map the lambda over it and the result is the following:
  1. [[3,-3],[4,-4],[5,-5]]  
·         The lambda is applied to every element and we get a list of lists. Finally, we just flatten the list and voila! We've applied a non-deterministic function to a non-deterministic value!
·         Non-determinism also includes support for failure. The empty list [] is pretty much the equivalent of Nothing, because it signifies the absence of a result. That's why failing is just defined as the empty list. The error message gets thrown away. Let's play around with lists that fail:
  1. ghci> [] >>= \x -> ["bad","mad","rad"]  
  2. []  
  3. ghci> [1,2,3] >>= \x -> []  
  4. []  
·         In the first line, an empty list is fed into the lambda. Because the list has no elements, none of them can be passed to the function and so the result is an empty list. This is similar to feeding Nothing to a function. In the second line, each element gets passed to the function, but the element is ignored and the function just returns an empty list. Because the function fails for every element that goes in it, the result is a failure.
·         Just like with Maybe values, we can chain several lists with >>=, propagating the non-determinism:
  1. ghci> [1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)  
  2. [(1,'a'),(1,'b'),(2,'a'),(2,'b')]  
·         The list [1,2] gets bound to n and ['a','b'] gets bound to ch. Then, we do return (n,ch) (or[(n,ch)]), which means taking a pair of (n,ch) and putting it in a default minimal context. In this case, it's making the smallest possible list that still presents (n,ch) as the result and features as little non-determinism as possible. Its effect on the context is minimal. What we're saying here is this: for every element in [1,2], go over every element in['a','b'] and produce a tuple of one element from each list.
·         Generally speaking, because return takes a value and wraps it in a minimal context, it doesn't have any extra effect (like failing in Maybe or resulting in more non-determinism for lists) but it does present something as its result.
·         When you have non-deterministic values interacting, you can view their computation as a tree where every possible result in a list represents a separate branch.
·         Here's the previous expression rewritten in do notation:
  1. listOfTuples :: [(Int,Char)]  
  2. listOfTuples = do  
  3.     n <- [1,2]  
  4.     ch <- ['a','b']  
  5.     return (n,ch)  
·         This makes it a bit more obvious that n takes on every value from [1,2] and ch takes on every value from ['a','b']. Just like with Maybe, we're extracting the elements from the monadic values and treating them like normal values and >>=takes care of the context for us. The context in this case is non-determinism.
·         Using lists with do notation really reminds me of something we've seen before. Check out the following piece of code:
  1. ghci> [ (n,ch) | n <- [1,2], ch <- ['a','b'] ]  
  2. [(1,'a'),(1,'b'),(2,'a'),(2,'b')]  
·         Yes! List comprehensions! In our do notation example, n became every result from [1,2] and for every such result, ch was assigned a result from ['a','b'] and then the final line put (n,ch) into a default context (a singleton list) to present it as the result without introducing any additional non-determinism. In this list comprehension, the same thing happened, only we didn't have to write return at the end to present (n,ch) as the result because the output part of a list comprehension did that for us.
·         In fact, list comprehensions are just syntactic sugar for using lists as monads. In the end, list comprehensions and lists in donotation translate to using >>= to do computations that feature non-determinism.
·         List comprehensions allow us to filter our output. For instance, we can filter a list of numbers to search only for that numbers whose digits contain a 7:
  1. ghci> [ x | x <- [1..50], '7' `elem` show x ]  
  2. [7,17,27,37,47]  
·         We apply show to x to turn our number into a string and then we check if the character '7' is part of that string. Pretty clever. To see how filtering in list comprehensions translates to the list monad, we have to check out the guard function and the MonadPlus type class. The MonadPlus type class is for monads that can also act as monoids. Here's its definition:
  1. class Monad m => MonadPlus m where  
  2.     mzero :: m a  
  3.     mplus :: m a -> m a -> m a  
·         mzero is synonymous to mempty from the Monoid type class and mplus corresponds to mappend. Because lists are monoids as well as monads, they can be made an instance of this type class:
  1. instance MonadPlus [] where  
  2.     mzero = []  
  3.     mplus = (++)  
·         For lists mzero represents a non-deterministic computation that has no results at all — a failed computation. mplus joins two non-deterministic values into one. The guard function is defined like this:
  1. guard :: (MonadPlus m) => Bool -> m ()  
  2. guard True = return ()  
  3. guard False = mzero  
·         It takes a boolean value and if it's True, takes a () and puts it in a minimal default context that still succeeds. Otherwise, it makes a failed monadic value. Here it is in action:
  1. ghci> guard (5 > 2) :: Maybe ()  
  2. Just ()  
  3. ghci> guard (1 > 2) :: Maybe ()  
  4. Nothing  
  5. ghci> guard (5 > 2) :: [()]  
  6. [()]  
  7. ghci> guard (1 > 2) :: [()]  
  8. []  
·         Looks interesting, but how is it useful? In the list monad, we use it to filter out non-deterministic computations. Observe:
  1. ghci> [1..50] >>= (\x -> guard ('7' `elem` show x) >> return x)  
  2. [7,17,27,37,47]  
·         The result here is the same as the result of our previous list comprehension. How does guard achieve this? Let's first see howguard functions in conjunction with >>:
  1. ghci> guard (5 > 2) >> return "cool" :: [String]  
  2. ["cool"]  
  3. ghci> guard (1 > 2) >> return "cool" :: [String]  
  4. []  
·         If guard succeeds, the result contained within it is an empty tuple. So then, we use >> to ignore that empty tuple and present something else as the result. However, if guard fails, then so will the return later on, because feeding an empty list to a function with >>= always results in an empty list. A guard basically says: if this boolean is False then produce a failure right here, otherwise make a successful value that has a dummy result of () inside it. All this does is to allow the computation to continue.
·         Here's the previous example rewritten in do notation:
  1. sevensOnly :: [Int]  
  2. sevensOnly = do  
  3.     x <- [1..50]  
  4.     guard ('7' `elem` show x)  
  5.     return x  
·         Had we forgotten to present x as the final result by using return, the resulting list would just be a list of empty tuples. Here's this again in the form of a list comprehension:
  1. ghci> [ x | x <- [1..50], '7' `elem` show x ]  
  2. [7,17,27,37,47]  
·         So filtering in list comprehensions is the same as using guard.
A knight's quest
·         Here's a problem that really lends itself to being solved with non-determinism. Say you have a chess board and only one knight piece on it. We want to find out if the knight can reach a certain position in three moves. We'll just use a pair of numbers to represent the knight's position on the chess board. The first number will determine the column he's in and the second number will determine the row.
·         Let's make a type synonym for the knight's current position on the chess board:
  1. type KnightPos = (Int,Int)  
·         So let's say that the knight starts at (6,2). Can he get to (6,1) in exactly three moves? Let's see. If we start off at (6,2)what's the best move to make next? I know, how about all of them! We have non-determinism at our disposal, so instead of picking one move, let's just pick all of them at once. Here's a function that takes the knight's position and returns all of its next moves:
  1. moveKnight :: KnightPos -> [KnightPos]  
  2. moveKnight (c,r) = do  
  3.     (c',r') <- [(c+2,r-1),(c+2,r+1),(c-2,r-1),(c-2,r+1)  
  4.                ,(c+1,r-2),(c+1,r+2),(c-1,r-2),(c-1,r+2)  
  5.                ]  
  6.     guard (c' `elem` [1..8] && r' `elem` [1..8])  
  7.     return (c',r')  
·         The knight can always take one step horizontally or vertically and two steps horizontally or vertically but its movement has to be both horizontal and vertical. (c',r') takes on every value from the list of movements and then guard makes sure that the new move, (c',r') is still on the board. If it it's not, it produces an empty list, which causes a failure and return (c',r')isn't carried out for that position.
·         This function can also be written without the use of lists as a monad, but we did it here just for kicks. Here is the same function done with filter:
  1. moveKnight :: KnightPos -> [KnightPos]  
  2. moveKnight (c,r) = filter onBoard  
  3.     [(c+2,r-1),(c+2,r+1),(c-2,r-1),(c-2,r+1)  
  4.     ,(c+1,r-2),(c+1,r+2),(c-1,r-2),(c-1,r+2)  
  5.     ]  
  6.     where onBoard (c,r) = `elem` [1..8] && r `elem` [1..8]  
·         Both of these do the same thing, so pick one that you think looks nicer. Let's give it a whirl:
  1. ghci> moveKnight (6,2)  
  2. [(8,1),(8,3),(4,1),(4,3),(7,4),(5,4)]  
  3. ghci> moveKnight (8,1)  
  4. [(6,2),(7,3)]  
·         Works like a charm! We take one position and we just carry out all the possible moves at once, so to speak. So now that we have a non-deterministic next position, we just use >>= to feed it to moveKnight. Here's a function that takes a position and returns all the positions that you can reach from it in three moves:
  1. in3 :: KnightPos -> [KnightPos]  
  2. in3 start = do   
  3.     first <- moveKnight start  
  4.     second <- moveKnight first  
  5.     moveKnight second  
·         If you pass it (6,2), the resulting list is quite big, because if there are several ways to reach some position in three moves, it crops up in the list several times. The above without do notation:
  1. in3 start = return start >>= moveKnight >>= moveKnight >>= moveKnight  
·         Using >>= once gives us all possible moves from the start and then when we use >>= the second time, for every possible first move, every possible next move is computed, and the same goes for the last move.
·         Putting a value in a default context by applying return to it and then feeding it to a function with >>= is the same as just normally applying the function to that value, but we did it here anyway for style.
·         Now, let's make a function that takes two positions and tells us if you can get from one to the other in exactly three steps:
  1. canReachIn3 :: KnightPos -> KnightPos -> Bool  
  2. canReachIn3 start end = end `elem` in3 start  
·         We generate all the possible positions in three steps and then we see if the position we're looking for is among them. So let's see if we can get from (6,2) to (6,1) in three moves:
  1. ghci> (6,2`canReachIn3` (6,1)  
  2. True  
·         Yes! How about from (6,2) to (7,3)?
  1. ghci> (6,2`canReachIn3` (7,3)  
  2. False  
·         No! As an exercise, you can change this function so that when you can reach one position from the other, it tells you which moves to take. Later on, we'll see how to modify this function so that we also pass it the number of moves to take instead of that number being hardcoded like it is now.
Monad laws
·         Just like applicative functors, and functors before them, monads come with a few laws that all monad instances must abide by. Just because something is made an instance of the Monad type class doesn't mean that it's a monad, it just means that it was made an instance of a type class. For a type to truly be a monad, the monad laws must hold for that type. These laws allow us to make reasonable assumptions about the type and its behavior.
·         Haskell allows any type to be an instance of any type class as long as the types check out. It can't check if the monad laws hold for a type though, so if we're making a new instance of the Monad type class, we have to be reasonably sure that all is well with the monad laws for that type. We can rely on the types that come with the standard library to satisfy the laws, but later when we go about making our own monads, we're going to have to manually check the if the laws hold. But don't worry, they're not complicated.
Left identity
·         The first monad law states that if we take a value, put it in a default context with return and then feed it to a function by using>>=, it's the same as just taking the value and applying the function to it. To put it formally:
·         return x >>= f is the same damn thing as f x
·         If you look at monadic values as values with a context and return as taking a value and putting it in a default minimal context that still presents that value as its result, it makes sense, because if that context is really minimal, feeding this monadic value to a function shouldn't be much different than just applying the function to the normal value, and indeed it isn't different at all.
·         For the Maybe monad return is defined as Just. The Maybe monad is all about possible failure, and if we have a value and want to put it in such a context, it makes sense that we treat it as a successful computation because, well, we know what the value is. Here's some return usage with Maybe:
  1. ghci> return 3 >>= (\x -> Just (x+100000))  
  2. Just 100003  
  3. ghci> (\x -> Just (x+100000)) 3  
  4. Just 100003  
·         For the list monad return puts something in a singleton list. The >>= implementation for lists goes over all the values in the list and applies the function to them, but since there's only one value in a singleton list, it's the same as applying the function to that value:
  1. ghci> return "WoM" >>= (\x -> [x,x,x])  
  2. ["WoM","WoM","WoM"]  
  3. ghci> (\x -> [x,x,x]) "WoM"  
  4. ["WoM","WoM","WoM"]  
·         We said that for IO, using return makes an I/O action that has no side-effects but just presents a value as its result. So it makes sense that this law holds for IO as well.
Right identity
·         The second law states that if we have a monadic value and we use >>= to feed it to return, the result is our original monadic value. Formally:
·         m >>= return is no different than just m
·         This one might be a bit less obvious than the first one, but let's take a look at why it should hold. When we feed monadic values to functions by using >>=, those functions take normal values and return monadic ones. return is also one such function, if you consider its type. Like we said, return puts a value in a minimal context that still presents that value as its result. This means that, for instance, for Maybe, it doesn't introduce any failure and for lists, it doesn't introduce any extra non-determinism. Here's a test run for a few monads:
  1. ghci> Just "move on up" >>= (\x -> return x)  
  2. Just "move on up"  
  3. ghci> [1,2,3,4] >>= (\x -> return x)  
  4. [1,2,3,4]  
  5. ghci> putStrLn "Wah!" >>= (\x -> return x)  
  6. Wah!  
·         If we take a closer look at the list example, the implementation for >>= is:
  1. xs >>= f = concat (map f xs)  
·         So when we feed [1,2,3,4] to return, first return gets mapped over [1,2,3,4], resulting in [[1],[2],[3],[4]]and then this gets concatenated and we have our original list.
·         Left identity and right identity are basically laws that describe how return should behave. It's an important function for making normal values into monadic ones and it wouldn't be good if the monadic value that it produced did a lot of other stuff.
Associativity
·         The final monad law says that when we have a chain of monadic function applications with >>=, it shouldn't matter how they're nested. Formally written:
·         Doing (m >>= f) >>= g is just like doing m >>= (\x -> f x >>= g)
·         Hmmm, now what's going on here? We have one monadic value, m and two monadic functions f and g. When we're doing(m >>= f) >>= g, we're feeding m to f, which results in a monadic value. Then, we feed that monadic value to g. In the expression m >>= (\x -> f x >>= g), we take a monadic value and we feed it to a function that feeds the result of f x tog. It's not easy to see how those two are equal, so let's take a look at an example that makes this equality a bit clearer.
·         Remember when we had our tightrope walker Pierre walk a rope while birds landed on his balancing pole? To simulate birds landing on his balancing pole, we made a chain of several functions that might produce failure:
  1. ghci> return (0,0) >>= landRight 2 >>= landLeft 2 >>= landRight 2  
  2. Just (2,4)  
·         We started with Just (0,0) and then bound that value to the next monadic function, landRight 2. The result of that was another monadic value which got bound into the next monadic function, and so on. If we were to explicitly parenthesize this, we'd write:
  1. ghci> ((return (0,0) >>= landRight 2) >>= landLeft 2) >>= landRight 2  
  2. Just (2,4)  
·         But we can also write the routine like this:
  1. return (0,0) >>= (\x -> 
  2. landRight 2 x >>= (\y -> 
  3. landLeft 2 y >>= (\z -> 
  4. landRight 2 z)))  
·         return (0,0) is the same as Just (0,0) and when we feed it to the lambda, the x becomes (0,0)landRight takes a number of birds and a pole (a tuple of numbers) and that's what it gets passed. This results in a Just (0,2) and when we feed this to the next lambda, y is (0,2). This goes on until the final bird landing produces a Just (2,4), which is indeed the result of the whole expression.
·         So it doesn't matter how you nest feeding values to monadic functions, what matters is their meaning. Here's another way to look at this law: consider composing two functions, f and g. Composing two functions is implemented like so:
  1. (.) :: (b -> c) -> (a -> b) -> (a -> c)  
  2. f . g = (\x -> f (g x))  
·         If the type of g is a -> b and the type of f is b -> c, we arrange them into a new function which has a type of a -> c, so that its parameter is passed between those functions. Now what if those two functions were monadic, that is, what if the values they returned were monadic values? If we had a function of type a -> m b, we couldn't just pass its result to a function of typeb -> m c, because that function accepts a normal b, not a monadic one. We could however, use >>= to make that happen. So by using >>=, we can compose two monadic functions:
  1. (<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> (a -> m c)  
  2. f <=< g = (\x -> g x >>= f)  
·         So now we can compose two monadic functions:
  1. ghci> let f x = [x,-x]  
  2. ghci> let g x = [x*3,x*2]  
  3. ghci> let h = f <=< g  
  4. ghci> h 3  
  5. [9,-9,6,-6]  
·         Cool. So what does that have to do with the associativity law? Well, when we look at the law as a law of compositions, it states that f <=< (g <=< h) should be the same as (f <=< g) <=< h. This is just another way of saying that for monads, the nesting of operations shouldn't matter.
·         If we translate the first two laws to use <=<, then the left identity law states that for every monadic function f,f <=< return is the same as writing just f and the right identity law says that return <=< f is also no different fromf.
·         This is very similar to how if f is a normal function, (f . g) . h is the same as f . (g . h)f . id is always the same as f and id . f is also just f.