Haskell 单变量变压器堆栈中的evalState
给定一个Haskell 单变量变压器堆栈中的evalState,haskell,monad-transformers,state-monad,Haskell,Monad Transformers,State Monad,给定一个mtlmonad堆栈,例如ExceptT字符串(WriterT字符串(状态sa)),我如何评估内部状态monad而不需要打开外部monad have :: ExceptT String (WriterT String (State s)) a f :: State s a -> a want :: ExceptT String (WriterT String Identity) a 我可以调用runExceptT,然后调用runWriterT,然后重新打包结果,但这样做似
mtl
monad堆栈,例如ExceptT字符串(WriterT字符串(状态sa))
,我如何评估内部状态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。我需要的是这样一个“拆分”monad transformer堆栈的功能:
split :: (MonadTrans s, Monad t) => (s t) a -> s (t a)
要么我没有发现此函数,要么解决方案的工作方式完全不同。我不知道有什么像您的
拆分那样通用,但是使用映射…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
我不知道有什么比您的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
在这种特殊情况下,似乎最简单的方法是使用MFunctor
的ExceptT e
和WriterT w
转换器的实例:
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
,上面的略微概括是直接的。在这种特殊情况下,似乎最简单的方法是使用除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)
因为states s=StateT s Identity
,上面的轻微概括是立即的。你不能。变压器添加的所有内容都是lift::ma->tma
。只有Monad
和MonadTrans
(整个“运行”的概念甚至不是Monad transformer概念的一部分),没有通用的方法来实现您想要做的事情。你可以像答案中那样有专门的函数,但没有通用的解决方案。你不能。变压器添加的所有内容都是lift::ma->tma
。只有Monad
和MonadTrans
(整个“运行”的概念甚至不是Monad transformer概念的一部分),没有通用的方法来实现您想要做的事情。您可以使用答案中的专用功能,但没有通用解决方案。起重机
正是我要找的。起重机
正是我要找的。