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)})}