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