如何转换StateT g (Either E) T
为ExceptT E (StateT g Identity) T
?
也许,一些混合traverse
和hoist
也许会有帮助.
你无法交换任意一对monad.但你可以交换这两个特殊的monad.如果你newtype
在那些monad变换器的定义中扩展s,这是最容易理解的.
特定
newtype StateT s m a = StateT { runStateT :: s -> m (s, a) }
和
newtype ExceptT e m a = ExceptT { runExceptT :: m (Either e a) }
扩展newtype
你的第一个类型表达式中的s给了我们同构
StateT s (Either e) a <-> s -> Either e (s, a)
而我们得到的第二个
ExceptT e (StateT s Identity) a <-> s -> (s, Either e a)
请注意,Either e (s, a)
可能包含或不包含s
,但(s, Either e a)
总是如此.现在,只需通过traverse
函数内部的元组就可以从后者转到前者,但是另一种方式需要一些特定于域的推理:如果计算抛出错误,那么我们应该将状态通过不变地传递给捕获器错误.(这是正确的做法吗?我觉得它很有争议.)
stateTEitherToExceptTState :: (s -> Either e (s, a)) -> (s -> (s, Either e a)) stateTEitherToExceptTState f s = case f s of Left e -> (s, Left e) Right sa -> fmap Right sa