Reputation: 229
I'm trying to implement a game in Haskell. I have a GameState type that manages things like the score, the players, and the rounds, where rounds are a RoundState type that manages the details of the game. To play the game, I have a function
playGame :: (RandomGen g) => State (GameState g) (Player, Int)
playGame = do playRound
winner <- checkForWinner
case winner of
Nothing -> playGame
Just x -> return x
where
checkForWinner :: RandomGen g => State (GameState g) (Maybe (Player, Int))
playRound :: RandomGen (g) => State (GameState g) ()
This isn't very interesting though, because I can't output anything to the screen without the IO monad.
How can I wrap this function in the IO monad while keeping the recursion on playGame?
Upvotes: 3
Views: 279
Reputation: 64740
Currently your monad is just state, no IO
:
State (GameState g)
What you want is a monad with state and IO:
type Game g = StateT (GameState g) IO
And now you can use the monad as you might expect
import Control.Monad.IO.Class (liftIO)
-- ...
playGame :: (RandomGen g) => Game g (Player, Int)
playGame = do
liftIO $ putStrLn "Look, I have IO"
winner <- checkForWinner
...
Upvotes: 7