Last active
August 29, 2015 14:14
-
-
Save ElectricCoffee/dc5744a64d2e48ebd39f to your computer and use it in GitHub Desktop.
guess my number game using the StateT monad, even though State isn't technically necessary
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Control.Monad.State | |
type Bound = (Int, Int) -- left is the lower bound, right is the upper | |
-- starting values | |
initial :: Bound | |
initial = (1, 100) | |
-- decrement integer | |
dec :: Int -> Int | |
dec x = x - 1 | |
-- increment integer | |
inc :: Int -> Int | |
inc x = x + 1 | |
-- 'guesses' the next number | |
guess :: Bound -> Int | |
guess (l, u) = (l + u) `div` 2 | |
-- modifies the current upper bound | |
smaller :: Monad m => StateT Bound m () | |
smaller = do | |
bd@(l, _) <- get | |
let newUpper = max l $ dec $ guess bd | |
put $ (l, newUpper) | |
-- modifies the current lower bound | |
bigger :: Monad m => StateT Bound m () | |
bigger = do | |
bd@(_, u) <- get | |
let newLower = min u $ inc $ guess bd | |
put $ (newLower, u) | |
{- Runs the game, by having the player tell the computer if the number is bigger or smaller | |
the game is run with runStateT game initial -} | |
game :: StateT Bound IO () | |
game = do | |
s <- get | |
liftIO $ print $ guess s | |
verdict <- (liftIO getLine) | |
case verdict of | |
"smaller" -> smaller >> game | |
"bigger" -> bigger >> game | |
"ok" -> return () | |
_ -> (liftIO $ putStrLn $ "Unknown verdict " ++ verdict) >> game | |
main :: IO () | |
main = do | |
runStateT game initial | |
return () |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment