## The Maybe Monad

Maybe is predefined and built in Haskell. Maybe is a type constructor whose definition is built-in as:

data Maybe a = Nothing | Just a

Its meaning as a type constructor is that Maybe accommodates cases where there might be no value. Indeed, in many cases we may have a value or our value may be null. In other languages we may have to have two different types for our value, in Haskell we only need Maybe. Maybe can be Nothing or Just our value. The words “Nothing” and “Just” have no meaning in Haskell. “Nothing” does not mean “null” in Haskell. Again, “Nothing” and “Just” have no meaning in Haskell. They are just words that define different values for the Maybe type constructor. It is how we assign these values and how we handle them in our code that gives them “meaning”.

So, we could have as easily created the following type:

data Maybe a = Nothing1 | Just1 a

or the following type:

data Maybe a = Invalid | Precisely a

or the following type:

data Maybe a = Nonexistent | Ditto a

and Maybe would have exactly the same functionality.

It is worth noting that Nothing precedes Just, because the creators of Maybe wanted Nothing to always be smaller when compared to Just with any value. Of course, this works by also adding the deriving (Show, Ord, Eq) expression at the end of Maybe’s declaration. We will see examples of this issue when I will provide a program that proves Maybe’s behavior.

Maybe is a type constructor, but Haskell has built-in code that elevates it to a Functor, an Applicative, and a Monad. I will now present you with the built-in code for Maybe, in order to understand how Maybe has been made to behave as a Functor, an Applicative, and a Monad. It is really easy to see:

```
data Maybe a = Nothing
| Just a

class Functor f where
fmap :: (a -> b) -> f a -> f b

instance Functor Maybe where
fmap f (Just x) = Just (f x)
fmap _ Nothing  = Nothing

class (Functor f) => Applicative f where
pure  :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b

instance Applicative Maybe where
pure = Just
(Just f) <*> (Just x) = Just (f x)
_        <*> _        = Nothing

class Monad m where
return :: a -> m a
(>>=)  :: m a -> (a -> m b) -> m b
(>>)   :: m a -> m b -> m b
fail   :: String -> m a

instance Monad Maybe where
return x = Just x
Just x >>= f  = f x
Nothing >>= f = Nothing
x >> y = x >>= \_ -> y
fail _ = Nothing

```

But the following code is general for Functors, Applicatives and Monads:

```class Functor f where
fmap :: (a -> b) -> f a -> f b

class (Functor f) => Applicative f where
pure  :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b

class Monad m where
return :: a -> m a
(>>=)  :: m a -> (a -> m b) -> m b
(>>)   :: m a -> m b -> m b
fail   :: String -> m a

```

Thus, the code that only applies to Maybe is:

```
data Maybe a = Nothing
| Just a

instance Functor Maybe where
fmap f (Just x) = Just (f x)
fmap _ Nothing  = Nothing

instance Applicative Maybe where
pure = Just
(Just f) <*> (Just x) = Just (f x)
_        <*> _        = Nothing

instance Monad Maybe where
return x = Just x
Just x >>= f  = f x
Nothing >>= f = Nothing
x >> y = x >>= \_ -> y
fail _ = Nothing

```

The last two lines in the previous program define the >> and fail functions that are optional to define. Thus the only code that is needed to elevate Maybe to a Monad is:

```
instance Monad Maybe where
return x = Just x
Just x >>= f  = f x
Nothing >>= f = Nothing

```

The following program proves that Maybe behaves as a type constructor, a Functor, an Applicative and a Monad:

```
module Main where

import Control.Applicative

main :: IO ()
main  =
do
putStrLn "Program begins."

putStrLn "Tests that prove that Maybe behaves as a type constructor."

print (Just 10)
print (Just 35 > Just 12)
print (Nothing < Just (-12))
print (Nothing < Just "test")

putStrLn "Tests that prove that Maybe behaves as a Functor."

print (fmap length (Just [1,2,3,4]))
print (fmap length Nothing)

putStrLn "Tests that prove that Maybe behaves as an Applicative."

print ((Just length) <*> (Just [1,2,3,4,5]))
print ((Just length) <*> Nothing)

putStrLn "Tests that prove that Maybe behaves as a Monad."

print (Just [1,2,3,4,5,6] >>= (\xs -> Just (length xs)))
print (Nothing >>= (\xs -> Just (length xs)))

putStrLn "Program ends."

```

The output of the previous program is:

```
Program begins.
Tests that prove that Maybe behaves as a type constructor.
Just 10
True
True
True
Tests that prove that Maybe behaves as a Functor.
Just 4
Nothing
Tests that prove that Maybe behaves as an Applicative.
Just 5
Nothing
Tests that prove that Maybe behaves as a Monad.
Just 6
Nothing
Program ends.

```

In the previous program we did not need to include the built-in code that makes Maybe behave as a type constructor, a Functor, an Applicative and a Monad, exactly because this code is already built-in.

Since Maybe is already predefined, we do not need to create it. But in order to demonstrate Haskell’s built-in code in a program, let the following program define our own Maybe type constructor: let us call it Maybe1. Here we go:

```
module Main where

import Control.Applicative

data Maybe1 a = Nothing1
| Just1 a
deriving (Show, Ord, Eq)

instance Functor Maybe1 where
fmap f (Just1 x) = Just1 (f x)
fmap _ Nothing1  = Nothing1

instance Applicative Maybe1 where
pure = Just1
(Just1 f) <*> (Just1 x) = Just1 (f x)
_        <*> _        = Nothing1

instance Monad Maybe1 where
return x = Just1 x
Just1 x >>= f  = f x
Nothing1 >>= f = Nothing1
x >> y = x >>= \_ -> y
fail _ = Nothing1

main :: IO ()
main  =
do
putStrLn "Program begins."

putStrLn "Tests that prove that Maybe1 behaves as a type constructor."

print (Just1 10)
print (Just1 35 > Just1 12)
print (Nothing1 < Just1 (-12))
print (Nothing1 < Just1 "test")

putStrLn "Tests that prove that Maybe1 behaves as a Functor."

print (fmap length (Just1 [1,2,3,4]))
print (fmap length Nothing1)

putStrLn "Tests that prove that Maybe1 behaves as an Applicative."

print ((Just1 length) <*> (Just1 [1,2,3,4,5]))
print ((Just1 length) <*> Nothing1)

putStrLn "Tests that prove that Maybe1 behaves as a Monad."

print (Just1 [1,2,3,4,5,6] >>= (\xs -> Just1 (length xs)))
print (Nothing1 >>= (\xs -> Just1 (length xs)))

putStrLn "Program ends."

```

The previous program produces the following output:

```
Program begins.
Tests that prove that Maybe1 behaves as a type constructor.
Just1 10
True
True
True
Tests that prove that Maybe1 behaves as a Functor.
Just1 4
Nothing1
Tests that prove that Maybe1 behaves as an Applicative.
Just1 5
Nothing1
Tests that prove that Maybe1 behaves as a Monad.
Just1 6
Nothing1
Program ends.

```

Update – Monday, March 10, 2014:

A great question was posed to me: Haskell implements the Maybe Monad as

Just x >>= f  = f x

But shouldn’t Haskell have implemented it as

Just x >>= f  = Just (f x)

instead? This way, the output of >>= will be of type m b, as is supposed to be according to the type signature of >>=, which is

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

Great question.

The answer is that Haskell is correct. This is because f represents a function with type signature a -> m b, thus the output of >>= will certainly be of the elevated type m b. So, when we see the symbol f in the definition (implementation) of >>=

Just x >>= f  = f x

we must realize that f is not of type a -> b but of type a -> m b, just as the declaration of >>= demands:

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

The function f in the definition

Just x >>= f  = f x

is the function (a -> m b) in the declaration

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

So x is of type a and the application of function f on x, denoted as f x, will produce output of type m b.

You see, it easy to get confused. This is because of the fact that when we provide the definition for fmap, f denotes a function with type a -> b. But when we provide the definition for >>=, f denotes a function with type a -> m b. So, please be careful as to what each argument means in each case.