monad 转换器堆栈中的 evalState
evalState in a monad transformer stack
给定一个 mtl
monad 堆栈,例如ExceptT String (WriterT String (State s a))
,如何在不需要解包外部 monad 的情况下评估内部状态 monad?
have :: ExceptT String (WriterT String (State s)) a
f :: State s a -> a
want :: ExceptT String (WriterT String Identity) a
我可以通过调用 runExceptT
然后调用 runWriterT
然后重新打包结果来完成此操作,但这似乎是错误的方法。
据我所试,fmap
或类似的东西不会起作用,因为 monad 转换器堆栈被视为一个完整的 monad。我需要的是 "split" monad 转换器堆栈的功能,如下所示:
split :: (MonadTrans s, Monad t) => (s t) a -> s (t a)
要么我没有找到这个函数,要么解决方案完全不同。
我不知道像你的 split
这样普遍的事情,但使用 map...T
函数可以防止显式操纵:
have :: ExceptT String (WriterT String (State s)) a
f :: State s a -> a
want :: ExceptT String (WriterT String Identity) a
want = mapExceptT (mapWriterT (return . f)) have
在这种特殊情况下,似乎最简单的方法是使用 ExceptT e
和 WriterT w
转换器的 MFunctor
实例:
import Control.Monad.Morph
floop :: Monad m
=> s
-> ExceptT e (WriterT w (StateT s m)) a
-> ExceptT e (WriterT w m) a
floop s = hoist (hoist $ flip evalStateT s)
自 State s = StateT s Identity
以来,上面的轻微概括是立竿见影的。
给定一个 mtl
monad 堆栈,例如ExceptT String (WriterT String (State s a))
,如何在不需要解包外部 monad 的情况下评估内部状态 monad?
have :: ExceptT String (WriterT String (State s)) a
f :: State s a -> a
want :: ExceptT String (WriterT String Identity) a
我可以通过调用 runExceptT
然后调用 runWriterT
然后重新打包结果来完成此操作,但这似乎是错误的方法。
据我所试,fmap
或类似的东西不会起作用,因为 monad 转换器堆栈被视为一个完整的 monad。我需要的是 "split" monad 转换器堆栈的功能,如下所示:
split :: (MonadTrans s, Monad t) => (s t) a -> s (t a)
要么我没有找到这个函数,要么解决方案完全不同。
我不知道像你的 split
这样普遍的事情,但使用 map...T
函数可以防止显式操纵:
have :: ExceptT String (WriterT String (State s)) a
f :: State s a -> a
want :: ExceptT String (WriterT String Identity) a
want = mapExceptT (mapWriterT (return . f)) have
在这种特殊情况下,似乎最简单的方法是使用 ExceptT e
和 WriterT w
转换器的 MFunctor
实例:
import Control.Monad.Morph
floop :: Monad m
=> s
-> ExceptT e (WriterT w (StateT s m)) a
-> ExceptT e (WriterT w m) a
floop s = hoist (hoist $ flip evalStateT s)
自 State s = StateT s Identity
以来,上面的轻微概括是立竿见影的。