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.