Lecture 21 — 2015-11-18
More monads
This lecture is written in literate Haskell; you can download the raw source.
Prof. Bruce lectured today. His code for Monad.hs
is below; you can also download his slides.
import Control.Monad.State
import Control.Monad.ST
import Data.Word
import Data.IORef
dormRooms =[("Jack",10),("Jill",20),("Ann",20)]
phonesForRooms = [(10,23434),(20,23435),(30,23438)]
getDormFor name [] = Nothing
getDormFor name ((nm,rm):rest) = if nm == name
then Just rm
else getDormFor name rest
getPhoneForRoom rm [] = Nothing
getPhoneForRoom rm ((rmnum,phone):rest) = if rm == rmnum
then Just phone
else getPhoneForRoom rm rest
getPhoneForName name rooms phones = case getDormFor name rooms of
Nothing -> Nothing
Just rm -> getPhoneForRoom rm phones
getPFN name rooms phones =
do rm <- getDormFor name rooms
num <- getPhoneForRoom rm phones
return num
echo :: IO()
echo = do str <- getLine
putStrLn str
ask :: String -> String -> IO()
ask prompt ansPrefix = do putStr (prompt++": ")
response <- getLine
putStrLn (ansPrefix ++ " " ++ response)
getInteger :: IO Integer -- type is necessary as read is ambiguous
getInteger = do putStr "Enter an integer: "
line <- getLine
return (read line) -- converts string to int then to IO Integer
type LCGState = Word32 -- 32 bit unsigned int, linear congruential generator
lcg :: LCGState -> (Integer, LCGState)
lcg s0 = (output, s1)
where s1 = 1103515245 * s0 + 12345
output = fromIntegral s1 * 2^16 `div` 2^32
-- fromIntegral converts to number
getRandom :: State LCGState Integer
getRandom = get >>= \s0 -> let (x,s1) = lcg s0
in put s1 >> return x
addThreeRandoms :: State LCGState Integer
addThreeRandoms = getRandom >>= \a ->
getRandom >>= \b ->
getRandom >>= \c -> return (a+b+c)
addTwoRandoms = do a <- getRandom
b <- getRandom
return (a+b)
whileIO :: IO Bool -> IO() -> IO()
whileIO b m = ifIO b
(do {m; whileIO b m})
(return())
ifIO :: IO Bool -> IO a -> IO a -> IO a
ifIO b tv fv = do { bv <- b;
if bv then tv else fv}
whileTest = do {v <- newIORef 0;
whileIO (do {x <- readIORef v; return (x<4)})
(do {x <- readIORef v;
print x;
writeIORef v (1+x)})}
notIO :: IO Bool -> IO Bool
notIO b = do {bv <- b; return (Prelude.not bv)}
untilIO :: IO() -> IO Bool -> IO()
untilIO m b = m >> whileIO (notIO b) m
untilTest = do {v <- newIORef 0;
untilIO (do {x <- readIORef v;
print x;
writeIORef v (1+x)})
(do {x <- readIORef v; return (x>4)})}