Online Book Reader

Home Category

Learn You a Haskell for Great Good! - Miran Lipovaca [128]

By Root 549 0
x ++ y). Inside this lambda, the y becomes "!". x is still 3, because we got it from the outer lambda. All this sort of reminds me of the following expression:

ghci> let x = 3; y = "!" in show x ++ y

"3!"

The main difference here is that the values in our >>= example are monadic. They are values with a failure context. We can replace any of them with a failure:

ghci> Nothing >>= (\x -> Just "!" >>= (\y -> Just (show x ++ y)))

Nothing

ghci> Just 3 >>= (\x -> Nothing >>= (\y -> Just (show x ++ y)))

Nothing

ghci> Just 3 >>= (\x -> Just "!" >>= (\y -> Nothing))

Nothing

In the first line, feeding a Nothing to a function naturally results in a Nothing. In the second line, we feed Just 3 to a function, and the x becomes 3. But then we feed a Nothing to the inner lambda, and the result of that is Nothing, which causes the outer lambda to produce Nothing as well. So this is sort of like assigning values to variables in let expressions, except that the values in question are monadic values.

To further illustrate this point, let’s write this in a script and have each Maybe value take up its own line:

foo :: Maybe String

foo = Just 3 >>= (\x ->

Just "!" >>= (\y ->

Just (show x ++ y)))

To save us from writing all these annoying lambdas, Haskell gives us do notation. It allows us to write the previous piece of code like this:

foo :: Maybe String

foo = do

x <- Just 3

y <- Just "!"

Just (show x ++ y)

It would seem as though we’ve gained the ability to temporarily extract things from Maybe values without needing to check if the Maybe values are Just values or Nothing values at every step. How cool! If any of the values that we try to extract from are Nothing, the whole do expression will result in a Nothing. We’re yanking out their (possibly existing) values and letting >>= worry about the context that comes with those values.

do expressions are just different syntax for chaining monadic values.

Do As I Do


In a do expression, every line that isn’t a let line is a monadic value. To inspect its result, we use <-. If we have a Maybe String and we bind it to a variable with <-, that variable will be a String, just as 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:

ghci> Just 9 >>= (\x -> Just (x > 8))

Just True

Because the left parameter of >>= is a Just value, the lambda is applied to 9, and the result is a Just True. We can rewrite this in do notation, as follows:

marySue :: Maybe Bool

marySue = do

x <- Just 9

Just (x > 8)

Comparing these two versions, it’s easy to see why the result of the whole monadic value is the result of the last monadic value in the do expression with all the previous ones chained into it.

Pierre Returns


Our tightrope walker’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. The exception is when the tightrope walker 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 are two birds landing on the left side, then two birds landing on the right, and then one bird landing on the left:

routine :: Maybe Pole

routine = do

start <- return (0, 0)

first <- landLeft 2 start

second <- landRight 2 first

landLeft 1 second

Let’s see if he succeeds:

ghci> routine

Just (3,2)

He does!

When we were doing these routines by explicitly writing >>=, we usually said something like return (0, 0) >>= landLeft 2, because landLeft 2 is a function that returns a Maybe value. However, with do expressions, each line must feature a monadic value. So we explicitly pass

Return Main Page Previous Page Next Page

®Online Book Reader