FreeT/ProgramT创建的monad变换器可以有类似于mtl的机制吗?Monad堆栈渗透类与免费/操作Monad变压器?
我对历史的理解如下。曾几何时,monad变压器被发明出来。然后人们开始将monad变压器堆叠在一起,然后发现在任何地方插入lift
都很烦人。然后有几个人发明了monad类,以便我们可以例如ask :: m r
in any monad m
such as MonadReader r m
。这是可能通过使每个单子类渗透每一个单子转换,像
(Monoid w, MonadState s m) => MonadState s (WriterT w m)
MonadWriter w m => MonadWriter w (StateT s m)
你需要对这样的实例声明的每对单子变压器,所以当有ñ单子变形金刚有ñ^2费用。然而,这并不是一个大问题,因为人们大多会使用预定义的单子,很少创建自己的单子。到目前为止,我明白这个故事,还有一些细节,例如在以下Q &答:
Avoiding lift with Monad Transformers
然后我的问题是与新自由单子http://hackage.haskell.org/package/free和运营单子http://hackage.haskell.org/package/operational。它们允许我们编写我们自己的DSL并将其用作monad,只需将语言定义为某种代数data
类型(Operational甚至不需要Functor
实例)。好消息是我们可以免费获得monads和monad变形金刚;那么monad课程呢?坏消息是,“我们很少定义我们自己的monad变压器”的假设不再成立。
作为试图理解这个问题,我做了两个ProgramT
s,使他们互相渗透;
https://github.com/nushio3/practice/blob/master/operational/exe-src/test-05.hs
的operational
包不支持单子类,所以我又实现minioperational
,并修改了它的工作,因为我需要; https://github.com/nushio3/minioperational
不过,我需要专门的实例声明
instance (Monad m, Operational ILang m) => Operational ILang (ProgramT SLang m) where
因为以下形式的一般性声明导致不可判定的实例。
instance (Monad m, Operational f m) => Operational f (ProgramT g m) where
我的问题是,我们怎样才能使它更容易让我们的业务单子互相渗透。或者,我希望能够渗透任何行动不便的单身汉。
我也想知道正确的技术术语,渗透 :)
谢谢你,彼得。在你的帮助下,我明白了如何使用''(* - > *)''结合两个类型构造函数。 https://github.com/nushio3/practice/blob/master/operational/exe-src/test-06.hs 编写可组合的口译员也一样简单: https://github.com/nushio3/practice/ blob/master/operational/exe-src/test-07.hs 我们甚至可以以'OverlappingInstances'为代价编写两种以上的语言。 https://github.com/nushio3/practice/blob/master/operational/exe-src/test-08.hs – nushio