3

私は自分のアプリケーションのゲーム状態を表す型を持っています。

Game { points :: Int }

State モナドでゲームロジックを定義します。

type GameState a = StateT Game a

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

一部の入力を単純に破棄できるようにしたい

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)

このような構文が必要です

addPoints num = do
    guard evenResult
    ...

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

ガードに当たってしまったらそのまま放置して、ブロック内は何もしないようにしたいです

どうすればいいですか?MonadPlus でほぼ可能に思えますが、mzero を使用して「状態に既にあるものを返す」ことができるかどうかはわかりません。ありがとう!

4

2 に答える 2

7

の上にインポートControl.Monad.Trans.Maybeして使用MaybeTStateTます。次に、 を使用mzeroして計算を中止するか、Kevin Ballard が言うように、isのguard condition場合に停止することができます。各ブロックを で囲むだけです。(モナドで定義したすべてのオプションを使用するか、必要な状態のモナドで動作するように型を変更する必要があることに注意してください。)conditionFalserunMaybeTliftStateToperation :: (MonadState m Game) => ...

直接使用していなくても、含まれているtransformersパッケージがある可能性があることに注意してください。Control.Monad.Trans.Maybemtlような標準モナドモジュールを含むパッケージは、それControl.Monad.Stateに依存しています。

于 2012-04-23T23:11:44.073 に答える
0

私は、質問に対する豚職人のコメントを肉付けしていると思います。

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

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

これは十分に近いです。ehird の答えの方が正しいと確信していますが、私が望んでいたよりもはるかに複雑に思えます。まだ学ぶことがたくさんあります:)

于 2012-04-24T15:40:32.073 に答える