# Monad Revision You can think of a monad as a container for a data type If $M$ is a monad, that means an element of $M$: $M_a$ is some sort of container where $a$ is any datatype One of the purposes of the `do` notation is to operate on the whole data structure by specify operations that must apply to each of the elements in the data structure, without having to specify the whole structure. $$ M_a=\{x_1, x_2, x_3,...\} $$ ```haskell do x <- m let y = x ** 2 + 7 return y ``` This extracts an element of type $a$ from $m$, squares and adds 7, and returns the new values as the data structure. Now $M$ is $$ M_b=\{y_1, y_2, y_3, \ldots\}\\or\\M=\{x_1^2+7, x_2^2+7, x_3^2+7, \ldots\} $$ The above can be written as a functor ```haskell fmap (\x -> x**2+7) m ``` Monads have more functionality than functors though If $x$ is an element of $a$ or $x :: a$ ```haskell x :: a return x -- we can also write pure x ``` Monads can have containers within containers Assume we have function `makeBlob` that maps every element of $a$ to an element of $M_b$ ```haskell makeBlob :: a -> Mb makeBlob x1 = do x <- m y <- makeBlob x return y -- this can be done instead with the bind operator m >>= makeBlob (>>=) :: Ma -> (a -> Mb) -> Mb ``` ## The IO Monad ```haskell square :: Int -> Int square x = x*x getInt :: IO Int getInt = do putStrLn "Enter a number: " s <- getLine -- getLine :: IO String return (read s :: Int) --read :: String -> Int squareIO :: IO Int squareIO = do x <- getInt let y <- square x return y -- as squareIO :: IO Int, returning y prints it out squareIO :: IO () -- unit type, with only one element, also called () squareIO = do x <- getInt let y <- square x putStrLn("The square " ++ (show x) ++ " is " (show y)) return () --return unit type -- in this case we dont even need return () as -- putStrLn :: IO () --recursively asks for list unless 0 entered getList :: IO [Int] getList = do x <- getInt if x == 0 then return [] else do xs <- getList return (x:xs) ```