[Haskell-cafe] Simple game: a monad for each player

Tillmann Rendel rendel at informatik.uni-marburg.de
Tue Apr 13 14:52:56 EDT 2010


Yves Parès wrote:
> data Player m = Player {
>     plName :: String,  -- unique for each player
>     plTurn :: GameGrid -> m Move  -- called whenever the player must play
> }

> What I try to avoid is having every player running in IO monad.

One could define the following players.

   human :: MonadIO m => Player m
   human = ...

   bot :: Monad m => Player m
   bot = ...

Note that these players are polymorphic in m, only assuming some minimal 
interface.

Now you can run both players in a single monad which is good enough for 
both, because it supports the union of the interfaces assumed by the 
various players. In this case, this monad could be IO, since it supports 
both MonadIO and Monad.

   changeBoard :: Board -> Move -> board
   changeBoard = ...

   play :: Player IO -> Player IO -> GameGrid -> IO GameResult
   play p1 p2 board do
     move <- plTurn p1 board
     play p2 p1 (changeBoard board move)

While this is probably not as expressive as what you want, it is 
reasonably simple, and it has the property that bot is not in the IO monad.

I have first seen this pattern in monadic interpreters, where you could 
have types like the following.

   eval :: (MonadReader Env m) => Expression -> m Value
   exec :: (MonadReader Env m, MonadIO m) => Statement -> m ()

These types reflect that the interpreted language permits side-effects
only in statements, but not in expressions. This is similar to your 
situation: You want your types to reflect that your game permits 
side-effects only in human players, not in artifical intelligences.

   Tillmann


More information about the Haskell-Cafe mailing list