我正在尝试采用例如ExceptT a (StateT A M)
某些具体类型A
和 monad M
,并将它们包装到我的新自定义 monad 中。
首先,我发现它StateT A M
经常出现在其他上下文中,因此我决定最好将它单独包装在 monad 中M1
,然后包装ExceptT a M1
到M2
.
所需的属性是创建M1
和M2
实例MonadState
和类M
(假设它被称为MyMonadClass
)。也M2
应该是MonadError
.
首先,我从简单的类型同义词开始:
type MyState = StateT A M
type MyBranch a = ExceptT a MyState
然后我想我会先画出实例声明(不实现实例),这就是我第一次陷入困境的地方。instance MonadState A (MyState)
似乎不是正确的语法。我想我必须创建newtype MyState' a = StateT a M
然后type MyState = MyState A
(让我们不要在不必要的地方使用语言扩展)。
但是,一旦我开始将同义词转换为newtype
声明,我就开始失去与StateT A M
andExceptT ...
类型的联系。
newtype MyState' s a = MyState' { runMyState :: s -> (s, a) }
type MyState = MyState' A
newtype MyBranch e a = MyBranch { runMyBranch :: MyState (Either e a) }
现在已经实现的转换器消失了,我想我正在尝试做一些没有多大意义的事情。所以我的问题是:如何将这种行为正确地包装到新的复合 monad 中,以便可以访问下面的层,从而避免不必要的提升,并使事情保持清晰和井井有条。