Simple StateT use
Jump to navigation
Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
A small example showing how to combine a State monad (in this case a unique supply), with the IO monad, via a monad transformer.
No need to resort to nasty mutable variables or globals!
import Control.Monad.State
main :: IO ()
main = runStateT code [1..] >> return ()
--
-- layer an infinite list of uniques over the IO monad
--
code :: StateT [Integer] IO ()
code = do
x <- pop
io $ print x
y <- pop
io $ print y
return ()
--
-- pop the next unique off the stack
--
pop :: StateT [Integer] IO Integer
pop = do
(x:xs) <- get
put xs
return x
io :: IO a -> StateT [Integer] IO a
io = liftIO
--
-- another example: a guessing game
-- (from http://scsibug.com/2006/11/28/a-simple-game-with-statet/)
--
module Main where
import System.Random
import Control.Monad.State
main = do answer <- getStdRandom (randomR (1,100)) -- think of a number
putStrLn "I'm thinking of a number between 1 and 100, can you guess it?"
guesses <- execStateT (guessSession answer) 0
putStrLn $ "Success in " ++ (show guesses) ++ " tries."
guessSession :: Int -> StateT Int IO ()
guessSession answer =
do gs <- lift getLine -- get guess from user
let g = read gs -- convert to number
modify (+1) -- increment number of guesses
case compare g answer of
LT -> do lift $ putStrLn "Too low"
guessSession answer
GT -> do lift $ putStrLn "Too high"
guessSession answer
EQ -> lift $ putStrLn "Got it!"