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概念的一部分),没有通用的方法来实现您想要做的事情。您可以使用答案中的专用功能,但没有通用解决方案。
起重机
正是我要找的。
起重机
正是我要找的。