![Page 1: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/1.jpg)
ArvindComputer Science and Artificial Intelligence Laboratory
M.I.T.
L13-1October 26, 2006 http://www.csg.csail.mit.edu/6.827
Monadic Programming
October 26, 2006
![Page 2: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/2.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-2
Outline• IO Monad
– Example: wc program– Some properties
• Monadic laws• Creating our own monads:
– Id: The simplest monad– State– Unique name generator– Emulating simple I/O– Exceptions
![Page 3: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/3.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-3
Monadic I/O
IO a: computation which does some I/O, then produces a value of type a.
(>>) :: IO a -> IO b -> IO b(>>=) :: IO a -> (a -> IO b) -> IO breturn :: a -> IO a
Primitive actionspecs:getChar :: IO CharputChar :: Char -> IO ()openFile, hClose, ...
Monadic I/O is a clever, type-safe idea which has become a rage in the FL community.
![Page 4: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/4.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-4
Word Count Program
wcs :: String -> Bool -> (Int,Int,Int) -> (Int,Int,Int)
wcs [] inWord (nc,nw,nl) = (nc,nw,nl)wcs (c:cs) inWord (nc,nw,nl) =
if (isNewLine c) then wcs cs False ((nc+1),nw,(nl+1))else if (isSpace c) then wcs cs False ((nc+1),nw,nl)else if (not inWord) then wcs cs True ((nc+1),(nw+1),nl)else wcs cs True ((nc+1),nw,nl)
Can we read the string from an input file as needed?
![Page 5: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/5.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-5
File Handling Primitives
type Filepath = Stringdata IOMode = ReadMode | WriteMode | ...data Handle = ... implemented as built-in type
openFile :: FilePath -> IOMode -> IO HandlehClose :: Handle -> IO ()hIsEOF :: Handle -> IO BoolhGetChar :: Handle -> IO Char
![Page 6: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/6.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-6
Monadic Word Count Program
wc filename =openFile filename ReadMode >>= \h ->wch h False (0,0,0) >>= \(nc,nw,nl) -> hClose h >>return (nc,nw,nl)
file name
wch :: Handle -> Bool -> (Int,Int,Int) -> IO (Int,Int,Int)
wcs :: String -> Bool -> (Int,Int,Int) -> (Int,Int,Int)
wc :: String -> IO (Int,Int,Int)
![Page 7: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/7.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-7
Monadic Word Count Program cont.
wch :: Handle -> Bool -> (Int,Int,Int) -> IO (Int,Int,Int)
wch h inWord (nc,nw,nl) =hIsEOF h >>= \eof -> if eof then return (nc,nw,nl) else hGetChar h >>= \c -> if (isNewLine c) then wch h False ((nc+1),nw,(nl+1)) else if (isSpace c) then wch h False ((nc+1),nw,nl) else if (not inWord) then wch h True ((nc+1),(nw+1),nl) else wch h True ((nc+1),nw,nl)
![Page 8: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/8.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-8
Calling WCmain :: IO ()
main = getArgs >>= \[filename] -> wc filename >>= \(nc,nw,nl) ->
putStr “ ” >>putStr (show nc) >>putStr “ ” >>putStr (show nw) >>putStr “ ” >>putStr (show nl) >>putStr “ ” >>putStr filename >>putStr “\n”
Once a value enters the IO monad it cannot leave it!
![Page 9: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/9.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-9
Error Handling
Monad can abort if an error occurs.Can add a function to handle errors:
catch :: IO a -> (IOError -> IO a) -> IO aioError :: IOError -> IO afail :: String -> IO a
catch echo (\err -> fail (“I/O error: ”++show err))
![Page 10: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/10.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-10
The Modularity Problem
Inserting a print (say for debugging):
sqrt :: Float -> IO Floatsqrt x =
let ... a = (putStrLn ...) :: IO Stringin a >> return result
Without the binding has no effect; the I/O has to be exposed to the caller:
One print statement changes the whole structure of the program!
![Page 11: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/11.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-11
Monadic I/O is Sequential
wc filename1 >>= \(nc1,nw1,nl1) -> wc filename2 >>= \(nc2,nw2,nl2) -> return (nc1+nc2, nw1+nw2, nl1+nl2)!
Monadic I/O is not conducive for parallel operations
The two wc calls are totally independent but the IO they perform must be sequentialized!
![Page 12: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/12.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-12
Syntactic sugar: do
do e -> e
do e ; dostmts -> e >> do dostmts
do p<-e ; dostmts -> e >>= \p-> do dostmts
do let p=e ; dostmts -> let p=e in do dostmts
do (nc1,nw1,nl1) <- wc filename1 (nc2,nw2,nl2) <- wc filename2return (nc1+nc2, nw1+nw2, nl1+nl2)
wc filename1 >>= \(nc1,nw1,nl1) -> wc filename2 >>= \(nc2,nw2,nl2) -> return (nc1+nc2, nw1+nw2, nl1+nl2)
versus
![Page 13: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/13.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-13
Are these program meaningful?
do (nc1,nw1,nl1) <- wc filename1 (nc2,nw2,nl2) <- wc filename1return (nc1+nc2, nw1+nw2, nl1+nl2)
foo = wc filename1do (nc1,nw1,nl1) <- foo (nc2,nw2,nl2) <- fooreturn (nc1+nc2, nw1+nw2, nl1+nl2)
![Page 14: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/14.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-14
Monadic Laws
1. do x <- return a ; m (\x -> do m) a
2. do x <- m ; return x m
3. do y <- (do x <- m ; n) ; o do x <- m; (do y <- n; o)
x FV(o)
do m ; n do _ <- m ; n
True for all monads. Only primitive operations distinguish monads from each other
m >> (n >> o) (m >> n) >> o
A derived axiom:
![Page 15: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/15.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-15
Properties of programs involving IO
putString [] = return ()
putString (c:cs) = putChar c >> putString cs
[] ++ bs = bs
(a:as) ++ bs = a : (as ++ bs)
putString as >> putString bs putString (as++bs)
One can prove this just using monadic laws without involving I/O properties
![Page 16: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/16.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-16
Monads and Let
1. let x = a in m (\x -> m) a2. let x = m in x m3. let y = (let x = m in n) in o
let x = m in (let y = n in o)x FV(o)
1. do x <- return a ; m (\x -> do m) a2. do x <- m ; return x m3. do y <- (do x <- m ; n) ; o do x <- m; (do y <- n; o)
x FV(o)
Monadic binding behaves like let
![Page 17: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/17.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-17
Monads and Let
• Relationship between monads and let is deep• This is used to embed languages inside
Haskell• IO is a special sublanguage with side effects
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 --*
![Page 18: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/18.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-18
Fib in Monadic Style
fib n = fib n =
if (n<=1) then n if (n<=1) then return n
else else
let do
n1 = n - 1 n1 <- return (n-1)
n2 = n - 2 n2 <- return (n-2)
f1 = fib n1 f1 <- fib n1
f2 = fib n2 f2 <- fib n2
in f1 + f2 return (f1+f2)
Note the awkward style: everything must be named!
![Page 19: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/19.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-19
Outline• IO Monad
– Example: wc program– Some properties
• Monadic laws• Creating our own monads:
– Id: The simplest monad– State– Unique name generator– Emulating simple I/O– Exceptions
![Page 20: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/20.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-20
Id: The Simplest Monadnewtype Id a = Id a
instance Monad Id where
return a = Id a
Id a >>= f = f a
runId (Id a) = a
• This monad has no special operations!• Indeed, we could just have used let• The runId operation runs our computation
For IO monad run was done outside the language
![Page 21: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/21.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-21
The State Monad• Allow the use of a single piece of mutable
state
put :: s -> State s ()
get :: State s s
runState :: s -> State s r -> (s,r)
instance Monad (State s)
![Page 22: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/22.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-22
The State Monad: Implementation
newtype State s r = S (s -> (s,r))
instance Monad (State s) where
return r = S (\s -> (s,r))
S f >>= g = S (\s -> let (s’, r) = f s
S h = g r
in h s’)
get = S (\s -> (s,s))
put s = S (\o -> (s,())
runState s (S c) = c s
![Page 23: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/23.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-23
Generating Unique Identifierstype Uniq = Int
type UniqM = State Int
runUniqM :: UniqM r -> r
runUniqM comp = snd (runState 0 comp)
uniq :: UniqM Uniq
uniq = do u <- get
put (u+1)
return u
![Page 24: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/24.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-24
Poor Man’s I/O
type PoorIO a = State (String, String)
putChar :: Char -> PoorIO ()putChar c = do (in, out) <- get put (in, out++[c])
getChar :: PoorIO ChargetChar = do (in, out) <- get
case in of a:as -> do put (as, out) return a [] -> fail “EOF”
![Page 25: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/25.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-25
Error Handling using Maybeinstance Monad Maybe where
return a = Just a
Nothing >>= f = Nothing
Just a >>= f = f a
fail _ = Nothing
Just a `mplus` b = Just a
Nothing `mplus` b = b
do m’ <- matrixInverse m
y <- matrixVectMult m x
return y
![Page 26: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/26.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-26
Combining Monads
• To simulate I/O, combine State and Maybe.• There are two ways to do this combination:
newtype SM s a = SM (s -> (s, Maybe a))newtype MS s a = MS (s -> Maybe (s, a))
SM MS ([],””) ([],””)
do putChar ‘H’ ([],”H”) ([],”H”) a <- getChar ([],”H”) Nothing putChar ‘I’ skipped`mplus` putChar ‘!’ ([],”H!”) ([],”!”)
![Page 27: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/27.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-27
Special Monads
• Operations inexpressible in pure Haskell
• IO MonadPrimitives must actually call the OSAlso used to embed C code
• State Transformer MonadEmbeds arbitrary mutable stateAlternative to M-structures + barriers
![Page 28: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/28.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-28
Extras
![Page 29: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/29.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-29
Monadic Laws
1. return a >>= \x -> m (\x -> m) a
2. m >>= \x -> return x m
3. (m >>= \x -> n) >>= \y -> o m >>= \x -> (n >>= \y -> o)
x FV(o)
True in every monad by definition. Primitive monadic operators distinguish one monad from another
m >> (n >> o) (m >> n) >> o
A derived axiom:
![Page 30: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/30.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-30
Base case
putString [] = return ()
[] ++ bs = bs
putString [] >> putString bs
return () >> putString bs putString bs putString ([]++bs)
![Page 31: Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L13-1 October 26, 2006 Monadic Programming October](https://reader035.vdocuments.mx/reader035/viewer/2022062713/56649f555503460f94c7960c/html5/thumbnails/31.jpg)
October 26, 2006 http://www.csg.csail.mit.edu/6.827 L13-31
Inductive case
putString (a:as) = putChar a >> putString as
(a:as) ++ bs = a : (as ++ bs)
putString (a:as) >> putString bs
(putChar a >> putString as) >> putString bs
putChar a >> (putString as>>putString bs) putChar a >> (putString (as ++ bs)) putString (a : (as ++ bs)) putString ((a:as) ++ bs)