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

现在,我不想运行此模拟的许多步骤并获取每个时间步骤的报告列表。

我通常在没有 a 的情况下执行此操作,ReaderT并用于传递如下参数:

 foo :: Enviroment -> State MyState Report

然后我会这样做:

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

我对liftand的类型感到困惑replicateM。是否有一种组合可以复制State MyState变压器内部的单子?

将来我会替换ReaderT Environment (State MyState) ReportforReaderT Environment (StateT MyState (Rand StdGen)) Report所以最好在拥有这种怪物类型之前把事情做好:(。

编辑:作为一个附带问题 - 有没有比使用更好的策略ReaderT Environment (State MyState) Report

4

2 回答 2

4

这里是replicateM的一个具体例子:

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 一次给出:

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

我可以连续运行 foo 七次:

*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 回答