Question

I have a type that represents game state for my application, for this question pretend it is something simple like:

Game { points :: Int }

I define my game logic with the State monad.

type GameState a = StateT Game a

addPoints :: Int -> GameState ()
addPoints num = do
    Game p <- get
    put $ Game (p+num)

I want to be able to simply discard some inputs

evenResult num = do
    Game p <- get
    return $ even (p + num) 

addPoints num = do
    isEven <- evenResult num
    if isEven then return () else do
    Game n <- get
    put $ Game (n+num)

I want a syntax that looks something like this

addPoints num = do
    guard evenResult
    ...

-- or this
addPoints num = do
    guardIsEvenResult
    ...

If it hits the guard, I want it to leave the state alone, and do nothing else in the block.

How can I do it? It seems close to possible with MonadPlus, but I'm not sure I could use mzero to say "return what you already have in your state". Thanks!

Was it helpful?

Solution

Import Control.Monad.Trans.Maybe and use MaybeT on top of StateT. Then, you can use mzero to abort the computation or, like Kevin Ballard says, guard condition to stop if condition is False; all you have to do is enclose each block in runMaybeT. (Note that you'll either have to lift every option you have defined on your StateT monad, or change their types to work with any monad with the state you require, like operation :: (MonadState m Game) => ....)

Note that you probably have the transformers package that Control.Monad.Trans.Maybe is contained in, even if you're not using it directly; the mtl package, which contains the standard monad modules like Control.Monad.State, depends on it.

OTHER TIPS

I think I'm sort of fleshing out pigworker's comment on the question.

ensure :: GameState Bool -> GameState () -> GameState ()
ensure p k = do 
  t <- p 
  when t k

addPoints num = do
  ensure (evenResult num) $ do
  ...

Which is close enough. I'm sure ehird's answer is more correct, but it also seems a lot more complicated than I wanted. So much to learn still :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top