私はいくつかのモナドアクションを持っています:State
アクションのいくつかは、現在の状態と任意選択で結果を生成する他の入力に基づいて決定を行います。この2つのタイプのアクションはお互いを呼び出します。ステートとステートトランスフォーマーのアクションの作成
State
とStateT Maybe
で2つのアクションタイプをモデル化しました。次の(考案された)例は私の現在のアプローチを示しています。
{-# LANGUAGE MultiWayIf #-}
import Control.Monad (guard)
import Control.Monad.Identity (runIdentity)
import Control.Monad.Trans.State
type Producer = Int -> State [Int] Int
type MaybeProducer = Int -> StateT [Int] Maybe Int
produce :: Producer
produce n
| n <= 0 = return 0
| otherwise = do accum <- get
let mRes = runStateT (maybeProduce n) accum
if | Just res <- mRes -> StateT $ const (return res)
| otherwise -> do res <- produce (n - 1)
return $ res + n
maybeProduce :: MaybeProducer
maybeProduce n = do guard $ odd n
modify (n:)
mapStateT (return . runIdentity) $
do res <- produce (n - 1)
return $ res + n
私はアクションチェック自体は非常に複雑(仕事の80%)であるので(したがって、単純なステートアクションにそれらを変換する)からチェックを分離して考えると、アクションに必要なバインディングを提供しています。 State
のアクションをStateT Maybe
に昇格させたくないのは、不正確なモデルになっているからです。
私が紛失しているより良いまたはより多くのeleganの方法がありますか?特に私はmapStateT
/runStateT
デュオが好きではありませんが、必要なようです。
PS:私は例が実際にWriter
ですけど、私はより良い本物の場合、それは不正確をもたらすので、私は、どちらかStateT Maybe
へState
行動を促進したくない
'mapStateT'は完全に上手くIMOです。私はちょうど 'ちょうど使用するだろう。 runIdentity'を引数として使用します。 – arrowd
おおよそ同じ質問(理論的だが):http://stackoverflow.com/questions/4138671/combining-statet-and-state-monads – gcnew