如何调用部分未嵌套的变压器?
How to call partially un-nest transformers?
给定嵌套的转换器 :: T2 of T1 of M0
,我如何利用 :: T2 of M0
、:: M2
?
这是一个示例:我正在编写一些需要读取、记录和状态的函数。定义:
gameRoutine :: WriterT [String] (ReaderT Env (State Viable)) NUM
如果我想打电话给一些
stateFunction :: State Viable NUM
甚至stateWithReaderFunction :: ReaderT Env (State Viable) NUM
,
我可以使用 lift
:
gameRoutine = do
x <- lift . lift $ stateFunction
y <- lift $ stateWithReaderFunction
但是我怎么调用 writerFunction :: Writer [String] a
呢?
如何调用writerStateFunction :: WriterT [String] (State Viable) NUM
(gameRoutine
定义的区别是缺少ReaderT
层)?
显然我不想将他们的定义提升为 gameRoutine
之一。
嗯,基本上 mtl
的想法是您 不需要 那样做。您不是使用该特定签名定义 writerStateFunction
,而是使用通用签名
定义它
writerStateFunction' :: (MonadWriter [String] m, MonadState Viable m)
=> m NUM
然后你尝试使用它的环境有一个额外的 Reader
层并不重要:这不会阻止 monad 同时拥有 MonadWriter
和 MonadState
功能。
你可以将一个Writer w a
变成一个MonadWriter
实例,比如:
import Control.Monad.Writer (MonadWriter, Writer, runWriter, tell)
lift' :: MonadWriter w m => Writer w a -> m a
lift' wr = do
let (a, w) = runWriter wr
tell w -- manually re-log the log msg
return a -- wrap value into new context
那么,你可以简单地写:
gameRoutine :: WriterT [String] (ReaderT Env (State Viable)) NUM
gameRoutine = do
a <- lift' writerFunction
只要writerFunction :: Writer [String] a
可以特化为a ~ NUM
。
给定嵌套的转换器 :: T2 of T1 of M0
,我如何利用 :: T2 of M0
、:: M2
?
这是一个示例:我正在编写一些需要读取、记录和状态的函数。定义:
gameRoutine :: WriterT [String] (ReaderT Env (State Viable)) NUM
如果我想打电话给一些
stateFunction :: State Viable NUM
甚至stateWithReaderFunction :: ReaderT Env (State Viable) NUM
,
我可以使用 lift
:
gameRoutine = do
x <- lift . lift $ stateFunction
y <- lift $ stateWithReaderFunction
但是我怎么调用 writerFunction :: Writer [String] a
呢?
如何调用writerStateFunction :: WriterT [String] (State Viable) NUM
(gameRoutine
定义的区别是缺少ReaderT
层)?
显然我不想将他们的定义提升为 gameRoutine
之一。
嗯,基本上 mtl
的想法是您 不需要 那样做。您不是使用该特定签名定义 writerStateFunction
,而是使用通用签名
writerStateFunction' :: (MonadWriter [String] m, MonadState Viable m)
=> m NUM
然后你尝试使用它的环境有一个额外的 Reader
层并不重要:这不会阻止 monad 同时拥有 MonadWriter
和 MonadState
功能。
你可以将一个Writer w a
变成一个MonadWriter
实例,比如:
import Control.Monad.Writer (MonadWriter, Writer, runWriter, tell)
lift' :: MonadWriter w m => Writer w a -> m a
lift' wr = do
let (a, w) = runWriter wr
tell w -- manually re-log the log msg
return a -- wrap value into new context
那么,你可以简单地写:
gameRoutine :: WriterT [String] (ReaderT Env (State Viable)) NUM
gameRoutine = do
a <- lift' writerFunction
只要writerFunction :: Writer [String] a
可以特化为a ~ NUM
。