1

次のようなものがあるとします。

data Environment = ...
data MyState = ...
data Report  = ...

updateState :: Environment -> MyState -> MyState
updateState = ...

report :: MyState -> Report
report = ...

foo :: ReaderT Environment (State MyState) Report 
foo = do env   <- ask
         state <- lift get
         let newState = updateState env state
         lift $ put newState
         return $ report newState

私の頭の中にあるのは、 に格納されるパラメータを持つ時間プロセスのシミュレーションですEnvironment。動的状態は に格納されMyState、シミュレーションの各時間ステップで収集したい情報は に格納されReportます。

ここで、このシミュレーションの多くのステップを実行して、各時間ステップのレポートを含むリストを取得したくありません。

私は通常、 なしでこれをReaderT行い、次のようにパラメーターを渡していました。

 foo :: Enviroment -> State MyState Report

それから私はただやります:

 manySteps :: Int -> Enviroment -> State MyState [Report]
 manySteps n env = replicate n $ (foo env) 

liftとの型で混乱していますreplicateMState MyStateトランスフォーマー内でモナドを複製する組み合わせはありますか?

将来的には交換ReaderT Environment (State MyState) ReportするReaderT Environment (StateT MyState (Rand StdGen)) Reportので、このモンスタータイプになる前に物事を正しく取得することをお勧めします:(.

編集:副次的な質問として-使用するよりも良い戦略はありReaderT Environment (State MyState) Reportますか?

4

2 に答える 2

4

ここでの複製Mの具体例:

import Control.Monad
import Control.Monad.Reader
import Control.Monad.State

data Environment = E Int deriving Show
data MyState = S Int deriving Show
data Report  = R String deriving Show

updateState :: Environment -> MyState -> MyState
updateState (E step) (S val) = S $! val + step

report :: MyState -> Report
report (S val) = R (show val)

foo :: ReaderT Environment (State MyState) Report 
foo = do env   <- ask
         state <- get -- lift was not needed
         let newState = updateState env state
         put newState -- lift was not needed
         return $ report newState

run e s m = runState (runReaderT m e) s

ReaderT には MonadState パススルー インスタンスがあるため、「リフト」を削除したことに注意してください。foo を 1 回実行すると、次のようになります。

*Main> run (E 10) (S 5) foo
(R "15",S 15)

foo を連続して 7 回実行できます。

*Main> run (E 10) (S 5) (replicateM 7 foo)
([R "15",R "25",R "35",R "45",R "55",R "65",R "75"],S 75)

上記でさらに明確にする必要があるのは何ですか?

于 2011-03-16T15:58:02.373 に答える
2

何かを使用する方法がわからない場合は、タイプを証明するだけで十分な場合があります

-- import Control.Monad.State
import Control.Monad
import Control.Monad.Trans.Reader

data Environment
data MyState
data Report
data State a b
instance Monad (State a)

foo = undefined :: ReaderT Environment (State MyState) Report

GHCiより

*Main> :t flip replicateM foo
flip replicateM foo
  :: Int -> ReaderT Environment (State MyState) [Report]
于 2011-03-16T16:17:29.377 に答える