Haskell 如何调用部分取消嵌套的转换器?
给定变压器嵌套Haskell 如何调用部分取消嵌套的转换器?,haskell,monads,monad-transformers,Haskell,Monads,Monad Transformers,给定变压器嵌套:T2/T1/M0,如何利用:T2/M0,::M2? 这里有一个例子:我正在编写一些需要读取、记录和状态的函数。定义: gameRoutine :: WriterT [String] (ReaderT Env (State Viable)) NUM 如果我想打电话 stateFunction::State-available-NUM 甚至是stateWithReaderFunction::ReaderT Env(State available)NUM 我可以使用电梯: gameR
:T2/T1/M0
,如何利用:T2/M0
,::M2
?
这里有一个例子:我正在编写一些需要读取、记录和状态的函数。定义:
gameRoutine :: WriterT [String] (ReaderT Env (State Viable)) NUM
如果我想打电话
stateFunction::State-available-NUM
甚至是stateWithReaderFunction::ReaderT Env(State available)NUM
我可以使用电梯:
gameRoutine = do
x <- lift . lift $ stateFunction
y <- lift $ stateWithReaderFunction
gameRoutine=do
基本上,mtl
的想法是你不需要这样做。您不是使用该特定签名定义writerStateFunction
,而是使用通用签名定义它
writerStateFunction' :: (MonadWriter [String] m, MonadState Viable m)
=> m NUM
那么,您尝试使用它的环境是否有一个额外的读卡器
层并不重要:这不会阻止monad同时具有MonadWriter
和MonadState
功能。您可以通过以下方式将Writer w
提升到实例中:
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
gameRoutine::WriterT[String](ReaderT-Env(State-available))NUM
gameRoutine=do
谢谢你的回答,让我大吃一惊。但是,如何使用writerStateFunction'
?我需要更改gameRoutine
定义吗?我不知道什么类型与约束匹配(MonadWriter[String]m,MonadState-m)
。这怎么可能?在我的理解中,一个转换器包装了一个单子,是一个单子,但为什么它实际上继承了内在单子的“特征”?当然还有很多东西需要学习。@IlyaSmagin对于任何Monad m
(以及另一个Monad转换器中的任何一种类型),类型WriterT[String](StateT m available)NUM
和StateT available(WriterT m[String])NUM都与该约束匹配!这就是全部要点——您实际上只是实例化不同类型的值以获得不同的顺序(不同的顺序为某些转换器提供了不同的语义!)。您描述的“继承”正是mtl
的机制-我建议使用@leftaroundabout ok将尝试阅读:)编译器需要-XFlexibleContexts
,所以这一定是一些狡猾的黑客行为,对吧?@IlyaSmagin:FlexibleContexts
没有太多黑客行为,这是一个扩展,你可以打开一点担心;它基本上只是禁用了标准Haskell的一些限制,这使得编写编译器变得更容易;但GHC不需要这个。当它请求可重叠的
或者甚至不连贯的
时,您应该对此保持警惕。。。