Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages...
Transcript of Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages...
![Page 1: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/1.jpg)
Lecture 7: Monads and IO
Søren Haagerup
Department of Mathematics and Computer ScienceUniversity of Southern Denmark, Odense
December 7, 2015
Some slides of this presentation are borrowed fromhttp://foswiki.cs.uu.nl/foswiki/pub/USCS/CourseSchedule/
C2-Monads-final.pdf
![Page 2: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/2.jpg)
Introduction• Monads are central to modern Haskell programming.• The IO type class is an example of a monad. Code written
with this monad is evaluated sequentially, and can makeuse of the IO operations of the Operating System:
main = docolors← forM [1, 2, 3, 4 ] (λa→ do
putStrLn ("Which color do you associate "
++ "with the number "++ show a ++ "?")
color← getLinereturn color)
putStrLn ("The colors that you associate "
++ "with 1, 2, 3 and 4 are: ")
mapM putStrLn colors
![Page 3: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/3.jpg)
Monadic computations often have special syntax...Haskell
pairs = do x← xsy← ysreturn (x, y)
Scala
val pairs = for { x← xsy← ys
} yield (x, y)
C# (LINQ)
var pairs = from x in xsfrom y in ysselect new {x, y};
![Page 4: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/4.jpg)
Asynchronous computationControl.Monad.Par
dofx← spawn (return (f x)) -- start evaluating (f x)gx← spawn (return (g x)) -- start evaluating (g x)a← get fx -- wait for fxb← get gx -- wait for gxreturn (a, b) -- return results
“Futures/promises” which exist in many languages, fit nicelyinto the monad abstraction.f and g could be functions doing a HTTP POST request, ordoing an expensive computation.
![Page 5: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/5.jpg)
Pure vs. impure languages• Monads can also help with making Haskell code shorter
and easier to read and write. This is the focus in thebeginning of this lecture.
• Pure languages• easy to reason about (equational reasoning)• may benefit from lazy evaluation,
• Impure languages• offer efficiency benefits• sometimes make possible a more compact mode of
expression
Using monads is an approach to integrate impure effects intopure programs.“In short, Haskell is the world’s finest imperative programminglanguage”
– Simon Peyton Jones
![Page 6: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/6.jpg)
Problems with pure functional programming
• Pure functional languages have this advantage: All flow ofdata is made explicit.
• And this disadvantage: Sometimes it is painfully explicit.
• The essence of an algorithm can become buried under theplumbing required to carry data from its point of creationto its point of use.
• We will now exemplify these statements, and later proposesolutions based on monads.
![Page 7: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/7.jpg)
Running example: A small interpreterWe introduce the type of terms, and an evaluation function:
data Term = Con Int | Div Term Term deriving Show
eval :: Term→ Inteval (Con a) = aeval (Div t u) = eval t ‘div‘ eval u
Examples of terms
answer, err :: Termanswer = (Div (Div (Con 1972) (Con 2)) (Con 23))err = (Div (Con 1) (Con 0))
We can evaluate...
eval answer = 42eval err = ⊥
![Page 8: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/8.jpg)
Extension 1/3: Adding error handling
data Term = Con Int | Div Term Term deriving Show
eval :: Term→ Inteval (Con a) = aeval (Div t u) = eval t ‘div‘ eval u
• We would like to add error handling to eval, such that theprogram will not crash when dividing by zero, but insteadreturn an error that can be used by other parts of theprogram.
• In impure languages, we would throw an exception
• What can we do in Haskell?
![Page 9: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/9.jpg)
Extension 1/3: Adding error handlingWe would like errors to be a value, and not ⊥:
data Error a = Raise Exception | Return a deriving Showtype Exception = String
eval :: Term→ Error Inteval (Con a) = Return aeval (Div t u) = case eval t of
Raise e→ Raise eReturn a→
case eval u ofRaise e→ Raise eReturn b→
if b ≡ 0then Raise "divide by zero"
else Return (a ‘div‘ b)
![Page 10: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/10.jpg)
Extension 2/3: Adding state - Counting the number ofoperations performed
data Term = Con Int | Div Term Term deriving Show
eval :: Term→ Inteval (Con a) = aeval (Div t u) = eval t ‘div‘ eval u
• We would like to add a a count of operations performedby the evaluation engine.
• In impure languages: increment a global variable
• What can we do in Haskell?
![Page 11: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/11.jpg)
Extension 2/3: Adding state - Counting the number ofoperations performed
type State s a = s→ (a, s)
eval :: Term→ State Int Inteval (Con a) x = (a, x)eval (Div t u) x = let (a, y) = eval t x in
let (b, z) = eval t y in(a ‘div‘ b, z + 1)
> eval answer 0(42, 2)
![Page 12: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/12.jpg)
Extension 3/3: Adding an execution tracedata Term = Con Int | Div Term Term deriving Show
eval :: Term→ Inteval (Con a) = aeval (Div t u) = eval t ‘div‘ eval u
• We would like to add an execution trace to the program -and write out which calls are made to eval, and what aretheir arguments?
• In impure languages: Execute a print statement inside eval• How yould we do in Haskell?
> putStrLn $ fst $ eval answereval (Con 1972) = 1972eval (Con 2) = 2eval (Div (Con 1972) (Con 2)) = 986eval (Con 23) = 23eval (Div (Div (Con 1972) (Con 2)) (Con 23)) = 42
![Page 13: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/13.jpg)
Adding an execution trace
type Writer a = (Output, a)type Output = String
eval :: Term→Writer Inteval (Con a) = (line (Con a) a, a)eval (Div t u) = let (x, a) = eval t in
let (y, b) = eval u in(x ++ y ++ line (Div t u) (a ‘div‘ b), a ‘div‘ b)
line :: Term→ Int→ Outputline t a = "eval ("++ show t ++ ") = "++ show a ++ "\n"
![Page 14: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/14.jpg)
Adding an execution trace
> putStrLn $ fst $ eval answereval (Con 1972) 6 1972eval (Con 2) 6 2eval (Div (Con 1972) (Con 2)) 6 986eval (Con 23) 6 23eval (Div (Div (Con 1972) (Con 2)) (Con 23)) 6 42
> putStrLn $ fst $ eval erreval (Con 1) 6 1eval (Con 0) 6 0eval (Div (Con 1) (Con 0)) 6 ∗ ∗ ∗Exception : divide by zero
![Page 15: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/15.jpg)
Adding an execution trace• From the discussion so far, it may appear that programs in
impure languages are easier to modify than those in purelanguages.
• But sometimes the reverse is true.• Say that it was desired to modify the previous program to
display the execution trace in the reverse order:
(x ++ y ++ line (Div t u) (a ‘div‘ b), a ‘div‘ b)
could be changed to
(line (Div t u) (a ‘div‘ b) ++ y ++ x, a ‘div‘ b)
• So - explicit data flow gives flexibility, but sometimes theexplicit way of programming is too explicit and buries theessence of the algoritm being implemented.
![Page 16: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/16.jpg)
What is a monad?
A monad is a triple (M, return, (>>=)) where
• M is a type constructor
• return :: a→M a is a function (also called unit)
• (>>=) :: M a→ (a→M b)→M b is a function (also calledbind)
![Page 17: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/17.jpg)
The old code
data Error a = Raise Exception | Return a deriving Showtype Exception = String
eval :: Term→ Error Inteval (Con a) = Return aeval (Div t u) = case eval t of
Raise e→ Raise eReturn a→
case eval u ofRaise e→ Raise eReturn b→
if b ≡ 0then Raise "divide by zero"
else Return (a ‘div‘ b)
![Page 18: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/18.jpg)
The new code
data Error a = Raise Exception | Return a deriving Showtype Exception = String
eval :: Term→ Error Inteval (Con a) = return aeval (Div t u) = do a← eval t
b← eval uif b ≡ 0
then raise "Divide by zero"
else return (a ‘div‘ b)
raise :: Exception→ Error araise e = Raise e
![Page 19: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/19.jpg)
The Error monad
data Error a = Raise Exception | Return a deriving Showtype Exception = String
instance (Monad Error) wherereturn = Returnm>>= k = case m of
Return a→ k aRaise e → Raise e
Verify the types• return :: a→ Error a• (>>=) :: Error a→ (a→ Error b)→ Error b
Question: How would you define a function f such that(Return x)>>= f = Return (x + 5) Note that we need nohandling of errors in the input given to f .
![Page 20: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/20.jpg)
The do notation
The do-notation
val = do a← eval tb← eval ureturn (a + b)
is just syntactic sugar for
val = eval t>>= λa→eval u>>= λb→return (a + b)
![Page 21: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/21.jpg)
How to define a monad for Maybe?
A simpler version of what we have just seen is:
data Maybe a = Nothing | Just a
Try to suggest definitions of the following functions:
• return :: a→Maybe a
• (>>=) :: Maybe a→ (a→Maybe b)→Maybe b
![Page 22: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/22.jpg)
Introducing state - The old code
type State s a = s→ (a, s)
eval :: Term→ State Int Inteval (Con a) x = (a, x)eval (Div t u) x = let (a, y) = eval t x in
let (b, z) = eval t y in(a ‘div‘ b, z + 1)
![Page 23: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/23.jpg)
What we would like to end up with...
type State s a = s→ (a, s)
eval :: Term→ State Int Inteval (Con a) = return aeval (Div t u) = do a← eval t
b← eval utickreturn (a ‘div‘ b)
Notice that the counting is done with the function tick, andkeeping track of the state variable is done behind the scenes!But we cannot exactly achieve this with standard Haskell.
We would need to activate the TypeSynonymInstancescompiler pragma, to declare State s as a Monad instance.
![Page 24: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/24.jpg)
type State s a = s→ (a, s)
return a = λx→ (a, x)m>>= k = λx→ let (a, y) = m x in
let (b, z) = k a y in(b, z)
tick :: State s ()tick = λx→ ((), x + 1)
eval :: Term→ State Int Inteval (Con a) = return aeval (Div t u) = eval t>>= λa→
eval u >>= λb→tick >>= \ →return (a ‘div‘ b)
> eval answer 0(42, 2)
![Page 25: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/25.jpg)
Making it an instance of Monad
For technical reasons, we need a newtype instead of anordinary type synonym type
newtype State s a = State {runState :: s→ (a, s)}
instance (Monad (State s)) wherereturn a = State (λx→ (a, x))m>>= k = State (λx→ let (a, y) = runState m x in
let (b, z) = runState (k a) y in(b, z))
tick :: M ()
tick = State (λx→ ((), x + 1))
![Page 26: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/26.jpg)
So we end up with the nice code that we wanted
eval :: Term→ State Int Inteval (Con a) = return aeval (Div t u) = do a← eval t
b← eval u← tick
return (a ‘div‘ b)
> runState (eval answer) 0(42, 2)
The do notation allows us to remove the ← (values which arethrown away)
![Page 27: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/27.jpg)
So we end up with the nice code that we wanted
eval :: Term→ State Int Inteval (Con a) = return aeval (Div t u) = do a← eval t
b← eval utickreturn (a ‘div‘ b)
> runState (eval answer) 0(42, 2)
![Page 28: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/28.jpg)
Example from testrun.hs in the Exam ProjectrandomTake :: Int→ [a]→ State StdGen ([a ], [a])randomTake m xs = randomElems (length xs) m xs
whererandomElem :: Int→ [a]→ State StdGen (a, [a ])randomElem n xs = do
i← state $ randomR (0, n − 1)let (ys, ys ′) = splitAt i xsreturn (xs !! i, ys ++ drop 1 ys ′)
randomElems :: Int→ Int→ [a ]→ State StdGen ([a], [a ])randomElems n m xs | m 6 0 ∨ n 6 0 = return ([ ], xs)randomElems n m xs = do
(y, xs ′)← randomElem n xs(ys, xs ′′)← randomElems (n − 1) (m − 1) xs ′
return (y : ys, xs ′′)
![Page 29: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/29.jpg)
Final variant: Adding execution trace
type M a = (Output, a)type Output = String
eval :: Term→M Inteval (Con a) = (line (Con a) a, a)eval (Div t u) = let (x, a) = eval t in
let (y, b) = eval u in(x ++ y ++ line (Div t u) (a ‘div‘ b), a ‘div‘ b)
line :: Term→ Int→ Outputline t a = "eval("++ show t ++ ")="++ show a ++ "\n"
![Page 30: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/30.jpg)
The code that we want to end up with...
eval :: Term→M Inteval (Con a) = do out (line (Con a) a)
return a
eval (Div t u) = do a← eval tb← eval uout (line (Div t u) (a ‘div‘ b))return (a ‘div‘ b)
![Page 31: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/31.jpg)
The definition of the monad...
type M a = (Output, a)type Output = String
return a = ("", a)m>>= k = let (x, a) = m in
let (y, b) = k a in(x ++ y, b)
out :: Output→M ()
out x = (x, ())
![Page 32: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/32.jpg)
Technicalities - introducing a newtype
newtype M a = Writer {runWriter :: (Output, a)}type Output = String
instance (Monad M) wherereturn a = Writer ("", a)m>>= k = let Writer (x, a) = m in
let Writer (y, b) = k a inWriter (x ++ y, b)
out :: Output→M ()
out x = Writer (x, ())
![Page 33: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/33.jpg)
Questions
Recall that a monad is a triple (M, return, (>>=)) where
return :: a→M a(>>=) :: M a→ (a→M b)→M b
Suggest definitions for (>>=) and return for the following typeconstructors:
• data Id a = Id a
• data [a ] = [ ] | a : [a ]
• data Tree a = Tip a | Node (Tree a) (Tree a)
![Page 34: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/34.jpg)
The List monad
Encoding multiple results and nondeterminism
Get the length of all words in a list of multi-line texts:
map length (concat (map words (concat (map lines txts))))
Easier to understand with a list comprehension:
[ length w | t← txts, l← lines t, w← words l]
We can also define sequencing and embedding, i.e., (>>=) andreturn :
(>>=) :: [a]→ (a→ [b ])→ [b]xs>>= f = concat (map f xs)return :: a→ [a ]return x = [x]
![Page 35: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/35.jpg)
Four equivalent pieces of code
map length (concat (map words (concat (map lines txts))))
[ length w | t← txts, l← lines t, w← words l]
do t← txtsl← lines tw← words lreturn (length w)
txts >>= λt→lines t >>= λl→words l>>= λw→return (length w)
![Page 36: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/36.jpg)
Adding filter functionalityodds = [x | x← [1 . . 10 ], odd x]
odds ′ = do x← [1 . . 10 ]-- how to filter odd x?
return x
odds ′ = do x← [1 . . 10 ]← if (odd x) then [()] else [ ]
return x
import Control.Monadodds ′ = do x← [1 . . 10 ]
guard (odd x)return x
![Page 37: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/37.jpg)
The Monad Laws
class Monad m wherereturn :: a→ m a(>>=) :: m a→ (a→ m b)→ m b
• The name “monad” is borrowed from category theory.
• A monad is an algebraic structure similar to a monoid.
• Monads have been popularized in functionalprogramming via the work of Moggi and Wadler.
• Every monad instance should satisfy the following laws:1. Left identity: return x>>= k ≡ k x2. Right identity: m>>= return ≡ m3. Associativity: m>>= (λa→ k a>>= l) ≡ (m>>= k)>>= l
![Page 38: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/38.jpg)
The IO Monad
Another type with actions that require sequencing. The IOmonad is special in several ways:
• IO is a primitive type, and (>>=) and return for IO areprimitive functions,
• I there is no (politically correct) function runIO :: IO a→ a,whereas for most other monads there is a correspondingfunction,
• values of IO a denote side-effecting programs that can beexecuted by the run-time system.
• Note that the specialty of IO has really not much to dowith being a monad.
![Page 39: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/39.jpg)
IO, Internally
Prelude> :i IOnewtype IO a
= GHC.Types.IO (GHC.Prim.State # GHC.Prim.RealWorld→ (#GHC.Prim.State # GHC.Prim.RealWorld, a#))
-- Defined in ‘GHC.Types’instance Monad IO -- Defined in ‘GHC.Base’instance Functor IO -- Defined in ‘GHC.Base’
Internally, GHC models IO as a state monad having the “realworld” as state!
![Page 40: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/40.jpg)
The role of IO in Haskell
More and more features have been integrated into IO, forinstance:
• classic file and terminal IOputStr, hPutStr
• referencesnewIORef , readIORef , writeIORef
• access to the systemgetArgs, getEnvironment, getClockTime
• exceptionsthrowIO, catch
• concurrencyforkIO
![Page 41: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/41.jpg)
IO examples
Stdout output
Main> putStr "Hi"HiMain> do {putChar ’H’; putChar ’i’; putChar ’\n’}Hi
Stdin input
Main> do {c← getChar; putStrLn ("’"++ [c ] ++ "’")}
z ′z ′
![Page 42: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/42.jpg)
IO examples
File IO
Main> do {h← openFile "TMP" WriteMode; hPutStrLn h "Hi"}Main> :q
Leaving GHCi
$ cat TMP
Hi
![Page 43: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/43.jpg)
IO examples
Side-effect: variables
do v← newIORef "text"modifyIoRef v (λt→ t ++ " and more text")
w← readIORef vprint w
Results in text and more text
![Page 44: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/44.jpg)
The role of IO in Haskell (contd.)
• A program that involves IO in its type can do everything.The absence of IO tells us a lot, but its presence does notallow us to judge what kind of IO is performed.
• It would be nice to have more fine-grained control on theeffects a program performs.
• For some, but not all effects in IO, we can use or buildspecialized monads.
![Page 45: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/45.jpg)
Lifting functions to monads
liftM :: (Monad m)⇒ (a→ b)→ m a→ m bliftM2 :: (Monad m)⇒ (a→ b→ c)→ m a→ m b→ m c. .liftM f m = do {x← m; return (f x)}liftM2 f m1 m2 = do {x1← m1; x2← m2; return (f x1 x2)}. .
Question: What is liftM (+1) [1 . . 5 ] ? Answer: Same asmap (+1) [1 . . 5 ]. The function liftM generalizes map to arbitrarymonads.
![Page 46: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/46.jpg)
Monadic map
mapM :: (Monad m)⇒ (a→ m b)→ [a ]→ m [b]mapM :: (Monad m)⇒ (a→ m b)→ [a]→ m ()
mapM f [ ] = return [ ]
mapM f (x : xs) = liftM2 (:) (f x) (mapM f xs)mapM f [ ] = return ()
mapM f (x : xs) = f x>>mapM f xs
![Page 47: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/47.jpg)
Sequencing monadic actions
sequence :: (Monad m)⇒ [m a]→ m [a ]sequence :: (Monad m)⇒ [m a]→ m ()
sequence = foldr (liftM2 (:)) (return [ ])
sequence = foldr (>>) (return ())
![Page 48: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/48.jpg)
Monadic fold
foldM :: (Monad m)⇒ (a→ b→ m a)→ a→ [b ]→ m afoldM op e [ ] = return efoldM op e (x : xs) = do r← op e xfoldM f r xs
![Page 49: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/49.jpg)
More monadic operations
Browse Control.Monad :
filterM :: (Monad m)⇒ (a→ m Bool)→ [a]→ m [a ]replicateM :: (Monad m)⇒ Int→ m a→ m [a]replicateM :: (Monad m)⇒ Int→ m a→ m ()
join :: (Monad m)⇒ m (m a)→ m awhen :: (Monad m)⇒ Bool→ m ()→ m ()
unless :: (Monad m)⇒ Bool→ m ()→ m ()
forever :: (Monad m)⇒ m a→ m ()
. . . and more!
![Page 50: Lecture 7: Monads and IOshaagerup.github.io/dm552/2015/files/lec7.pdfPure vs. impure languages Monads can also help with making Haskell code shorter and easier to read and write. This](https://reader033.fdocuments.in/reader033/viewer/2022042311/5ed9c3a2cd0f9068bb61c9df/html5/thumbnails/50.jpg)
Exercises Wednesday
• Will be relevant for the exam project.
• minimax and expectimax will be discussed.
• Different tree algorithms on “Game trees”
• The exercises next week will be on Real World Haskell
• The labs on friday next week will be about monadproblems, but you can also work on your project.