# 3. Monads

Created Saturday 23 August 2014

## Overview

- Familiar examples of monads
- Common functionality for all Monads
- Monad type class
- do-notation

## Monad Examples

__IO__**return :: a -> IO a****unreturn :: IO a -> a**—__IMPOSSIBLE__**bindIO :: IO a -> (a -> IO b) -> IO b**- Manipulate IO values but leave them in IO
- Unpacks an IO value and packs it back to IO function after manipulation
__List__**singleton :: a -> [a]****unsingleton :: [a] -> a**—__IMPOSSIBLE__**flatMap :: [a] -> (a -> [b]) -> [b]**

**GHCi> flatMap [1,7,11] (\x -> [x, x+1])**

**Result: [1,2,7,8,11,12]**

__Maybe__**data Maybe a = Nothing | Just a****Just :: a -> Maybe a****unJust :: Maybe a -> a**—__IMPOSSIBLE__**bindMaybe :: Maybe a -> (a -> Maybe b) -> Maybe b**

**GHCi> bindMaybe Nothing (\x ->**

**if (x==0)**

**then Nothing**

**else Just (2*x))**

**Result: Nothing**

**GHCi> bindMaybe (Just 0) (\x ->**

**if (x==0)**

**then Nothing**

**else Just (2*x))**

**Result: Nothing**

**GHCi> bindMaybe (Just 1) (\x ->**

**if (x==0)**

**then Nothing**

**else Just (2*x))**

**Result: 2**

__Any type with these 2 operations: packaging up and modifying something inside a package is a MONAD__

## Common Functionality for All Monads

- Any monad must support return function like these:
- Which takes an ordinary value and packages it up inside a monad type

**return :: a -> IO a**

**return :: a -> [a]**

**return :: a -> Maybe a**

- Any monad must support bind function like these:
- To modify a value or values inside a monad

**bind :: IO a -> (a -> IO b) -> IO b**

**bind :: [a] -> (a -> [b]) -> [b]**

**bind :: Maybe a -> (a -> Maybe b) -> Maybe b**

- The join function is supported by monads:
- Takes a value that is nested inside 2 layers of a monad either an IO value, a list of lists, etc.., join effectively removes the outer layer

**join :: IO (IO a) -> IO a**

- For nested IO value: the outer IO action produces another IO action, which is then executed returning the value inside the inner IO action

**join :: a -> [a]**

- For list of lists join concatenates all lists together

**join :: Maybe (Maybe a) -> Maybe a**

- For Maybe if the value is nested Just value, then it returns just the inner value. If value is Just Nothing then there is no value to return, so it gives Nothing

**join mmx = bind mmx id**

## Monad Type Class

- Type class of parameterized types

**class Monad m where**

**return :: a -> m a**

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

- Captures common pattern in
**IO**,**list**, and**Maybe**(and all other monads) - The type
**m**is a monad - First the
**monad**must have a**return**function which takes a value and wraps it up inside a monad type**m** - Also needs support a
**bind**operation. Bind is an operator (**(>>=)**) rather than a named function because this is nicer for chaining together multiple binds - By using a type class constraint, we then able to write functions like
**join**in a completely general way so that they work for any**monad**

**join :: Monad m => m (m a) -> m a**

**join mmx = mmx >>= id**

## do-Notation

- A syntactic sugar
- The following function doesn't use
**do**-notatin and looks complicated

**addM :: Monad m => m Int -> m Int -> m Int**

**addM mx my =**

**mx >>= (\x -> my >>= (\y -> return (x + y)))**

- This function takes 2
**Int**values each inside the same**monad****m**and returns a sum inside the same**monad** - The 1st argument
**mx**is passed to the**bind**operator which extracts the value from the**monad**and passes it to the 1st anonymous function as the**x**argument. Then, another**bind**operator is used to extract the 2nd value as**y**, and finally with both**x**and**y**available they can be added together as ordinary**Int**s the result can be package back up into the**monad**using**return**. - The following function does use
**do**-notation - Behind the scene it really runs the previous code

**addM' :: Monad m => m Int -> m Int -> m Int**

**addM' mx my = do**

**x <- mx**

**y <- my**

**return (x + y)**

EXAMPLE

**people = ["Alice", "Bob", "Eve"]**

**items = ["car", "puppy"]**

**missing = do**

**person <- people --will extract all elements to apply all the following actions to them**

**item <- items --the same (refer to the flatMap)**

**return (person ++ " lost a " ++ item)**

Backlinks: