私は Haskell で小さなゲームを書こうとしていますが、渡すためにかなりの量の状態が必要です。Stateモナドで状態を隠してみたい
今、私は問題に遭遇しました: 状態と引数を取る関数は、状態モナドで動作するように書くのは簡単でした. しかし、引数として状態を受け取るだけの関数もあります (そして、変更された状態、またはおそらく何か他のものを返します)。
コードの一部に、次の行があります。
let player = getCurrentPlayer state
状態を取らず、代わりに書きたい
player <- getCurrentPlayerM
現在、その実装は次のようになっています
getCurrentPlayer gameState =
(players gameState) ! (on_turn gameState)
そして、次のように書くことで State モナドで動作させるのに十分簡単に思えました:
getCurrentPlayerM = do state <- get
return (players state ! on_turn state)
しかし、それはghcからの苦情を引き起こします! 「get」の使用に起因する (MonadState GameState m0) のインスタンスはありません。State モナド形式で nullary でないことを除いて、非常によく似た関数を既に書き直していたので、直感で次のように書き直しました。
getCurrentPlayerM _ = do state <- get
return (players state ! on_turn state)
そして確かに、それは機能します!しかし、もちろん getCurrentPlayerM () として呼び出す必要があり、それを行うのは少しばかげています。そもそも言い争いは避けたかった!
追加の驚き: ghci でそのタイプを見ると、
getCurrentPlayerM :: MonadState GameState m => t -> m P.Player
しかし、コードでそれを明示的に設定しようとすると、別のエラーが発生します。「制約 MonadState GameState m の非型変数引数」と、それを許可する言語拡張の提案です。私の GameState は型であり、型クラスではないためだと思いますが、実際には受け入れられているのに、それについて明示しようとすると受け入れられない理由は、もっと混乱しています。
要約すると:
- Stateモナドにnullary関数を書けないのはなぜですか?
- 回避策関数が実際に持っている型を宣言できないのはなぜですか?