monad 转换器中的内部 monad 是否有 `replicateM` 函数?

发布于 2024-10-22 03:59:24 字数 1250 浏览 1 评论 0原文

假设我有这样的东西:

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中> 我希望在模拟的每个时间步中收集的信息将存储在报告中。

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

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

 foo :: Enviroment -> State MyState Report

然后我会这样做:

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

我对 lift的类型感到困惑复制M。是否有一个组合可以在变压器内复制 State MyState monad?

将来我会将 ReaderT Environment (State MyState) Report 替换为 ReaderT Environment (StateT MyState (Rand StdGen)) Report,因此最好在执行此操作之前先把事情做好怪物类型:(。

编辑:作为一个附带问题-是否有比使用ReaderT环境(State MyState)报告更好的策略?

Suppose I have something like this:

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

What's in my head are simulations of a time process in which I have parameters that will be stored in Environment, the dynamical state will be stored in MyState and info I wish to collect in each time step of the simulation will be stored in Report.

Now, I wan't to run many steps of this simulation and get a list with the reports for each time step.

I usually did this without a ReaderT and used to pass the parameters like this:

 foo :: Enviroment -> State MyState Report

Then I would just do:

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

I'm getting confused with the types of lift and replicateM. Is there a combination that would replicate the State MyState monad inside the transformer?

In the future I'll replace ReaderT Environment (State MyState) Report for ReaderT Environment (StateT MyState (Rand StdGen)) Report so it's better to get things right before having this monster type :(.

edit: as a side question - is there a better strategy than using ReaderT Environment (State MyState) Report ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

没有心的人 2024-10-29 03:59:24

这里有一个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

请注意,我删除了“lift”,因为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)

上面的内容需要更多说明吗?

A concrete example of replicateM here:

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

Note that I removed the "lift" since the ReaderT has a MonadState pass-through instance. Running foo once gives:

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

I can run foo seven times in a row:

*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)

What in the above needs more clarification?

誰認得朕 2024-10-29 03:59:24

有时,如果您不确定如何使用

-- 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]

Sometimes it's enough to prove type if you unsure in the way to use something

-- 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

Than in GHCi

*Main> :t flip replicateM foo
flip replicateM foo
  :: Int -> ReaderT Environment (State MyState) [Report]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文