[Haskell-cafe] Re: 'Proper' use of the State monad

2007-05-01 Thread DavidA
 1) Using State GameState r and then call execState for each game event
 (i.e. user input) so I can do IO
 2) Using StateT GameState IO () and have the entire game live in one
 big execStateT call. (I note XMonad does something similar.)

I'm also interested in the answer to this question. One concern I would have 
about option 2 is that it looks like it breaks encapsulation, to use a phrase 
from OOP.

What I mean is, it seems like good design would mean that you could write and 
test the game logic totally independently of any IO. Game functions such 
as makeMove ought to have type signatures that don't involve any IO. Can this 
be achieved in option 2?


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: 'Proper' use of the State monad

2007-05-01 Thread Sebastian Sylvan

On 5/1/07, DavidA [EMAIL PROTECTED] wrote:


 1) Using State GameState r and then call execState for each game event
 (i.e. user input) so I can do IO
 2) Using StateT GameState IO () and have the entire game live in one
 big execStateT call. (I note XMonad does something similar.)

I'm also interested in the answer to this question. One concern I would
have
about option 2 is that it looks like it breaks encapsulation, to use a
phrase
from OOP.

What I mean is, it seems like good design would mean that you could write
and
test the game logic totally independently of any IO. Game functions such
as makeMove ought to have type signatures that don't involve any IO. Can
this
be achieved in option 2?



You could, of course, do both.

I do think it's a good idea to write your own game monad which
encapsulates all of the unsafe functions that you might want to do in an
application specific approprate way, rather than just having your unsafe
skin be the IO monad. So for example, if you want to spawn an actor in the
game world and attach an AI thread to govern its behaviour you'd need a
function which interanlly uses forkIO, sets up a bunch of TVars for
messaging etc., but from the Game monad's pespective that can be
encapsulated. There *are* things which are just inherently imperative in
nature, and are easier to do like that (threads with message passing, for
example, is not necessarily bad, sometimes they are the Right Abstraction --
actor AI is probably a good example), but you can make it a lot nicer and
less unsafe by writing your own unsafe skin which supplies slightly safer
encapsulations tailored for your specific application.

But of course, you could have another monad which ONLY deals with pure
changes to the game state that you then evaluate from the underlying monad.
So the GameEngine monad is the unsafe skin, and then you have the Game
monad which just does a pure computation on the game state. Then you'd have
a function like:

game :: Game a - GameEngine a
game g = do
 state - get
 gstate - gameState state
 let ( res, gstate' ) = runState g
 put ( state{ gameState = gstate' } )
 return res

Which simply runs a game action on the game part of the GameEngine state.

--
Sebastian Sylvan
+44(0)7857-300802
UIN: 44640862
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: 'Proper' use of the State monad

2007-05-01 Thread Yitzchak Gale

DavidA wrote:

What I mean is, it seems like good design would mean that you could write and
test the game logic totally independently of any IO. Game functions such
as makeMove ought to have type signatures that don't involve any IO. Can this
be achieved in option 2?


Here is one way:

For functions that do not need IO, use types that look like:

MonadState GameState m = ... - m a

For functions that only do IO without refering to the
game state, use:

MonadIO m = ... - m a

For functions that do both, use:

(MonadIO m, MonadState GameState m) = ... - m a

Testing of the pure game functions can use
State GameState, testing of pure IO functions can
use IO, and production can use StateT GameState IO.

-Yitz
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe