Skip to content

Instantly share code, notes, and snippets.

@ElectricCoffee
Last active August 29, 2015 14:14
Show Gist options
  • Save ElectricCoffee/dc5744a64d2e48ebd39f to your computer and use it in GitHub Desktop.
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
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