Online Book Reader

Home Category

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

By Root 565 0
>>= 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 understanding 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:

ghci> (\x -> Just (x+1)) 1

Just 2

ghci> (\x -> Just (x+1)) 100

Just 101

If we feed it 1, it evaluates to Just 2. If we give it the number 100, the result is Just 101. It seems very straightforward. But how do we feed a Maybe value to this function? If we think about how Maybe acts as an applicative functor, answering this is pretty easy. We feed it a Just value, take what’s inside the Just, and apply the function to it. If we give it a Nothing, then we’re left with a function but Nothing to apply it to. In that case, let’s just do what we did before and say that the result is Nothing.

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. Here it is in code:

applyMaybe :: Maybe a -> (a -> Maybe b) -> Maybe b

applyMaybe Nothing f = Nothing

applyMaybe (Just x) f = f x

Now let’s play with it. We’ll use it as an infix function so that the Maybe value is on the left side and the function is on the right:

ghci> Just 3 `applyMaybe` \x -> Just (x+1)

Just 4

ghci> Just "smile" `applyMaybe` \x -> Just (x ++ " :)")

Just "smile :)"

ghci> Nothing `applyMaybe` \x -> Just (x+1)

Nothing

ghci> Nothing `applyMaybe` \x -> Just (x ++ " :)")

Nothing

In this example, when we used applyMaybe with a Just value and a function, the function was simply applied to the value inside the Just. When we tried to use it with a Nothing, the whole result was Nothing. What about if the function returns a Nothing? Let’s see:

ghci> Just 3 `applyMaybe` \x -> if x > 2 then Just x else Nothing

Just 3

ghci> Just 1 `applyMaybe` \x -> if x > 2 then Just x else Nothing

Nothing

The results are just what we expected. If the monadic value on the left is a Nothing, the whole thing is Nothing. And if the function on the right returns a Nothing, the result is Nothing again. This is similar to when we used Maybe as an applicative and we got a Nothing result if there was a Nothing somewhere in the mix.

It looks like we’ve figured out how to take a fancy value, feed it to a function that takes a normal value, and return a fancy one. We did this by keeping in mind that a Maybe value represents a computation that might have failed.

You might be asking yourself, “How is this useful?” It may seem like applicative functors are stronger than monads, since applicative functors allow us to take a normal function and make it operate on values with contexts. In this chapter, you’ll see that monads, as an upgrade of applicative functors, can also do that. In fact, they can do some other cool stuff that applicative functors can’t do.

We’ll come back to Maybe in a minute, but first, let’s check out the type class that belongs to monads.

The Monad Type Class

Just like functors have the Functor type class, and applicative functors have the Applicative type class, monads come with their own type class: Monad! (Wow, who would have thought?)

class Monad m where

return :: a -> m a

(>>=) :: m a -> (a -> m b) -> m b

(>>) :: m a -> m b -> m b

x >> y = x >>= \_ -> y

fail :: String -> m a

fail msg = error msg

The first line says class Monad m where. But wait, didn’t I say that monads are just beefed-up applicative functors? Shouldn’t there be a class constraint in there along the lines of class (Applicative m) = > Monad m where, so that a type must be an applicative functor before it can be made a monad? Well, there should, but when Haskell was made, it hadn’t occurred to people that applicative functors were a good fit for Haskell. 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

Return Main Page Previous Page Next Page

®Online Book Reader