Simple StateT use
Jump to navigation
Jump to search
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!"