我有两个 Free monads 用于不同上下文中的不同操作。但是,如果特定操作在上下文中,则一个 ( major
) DSL 需要包含另一个 ( ):action
import Control.Monad.Free
data ActionFunctor next = Wait Timeout next
| Read URI next
instance Functor ActionFunctor where
fmap f (Wait timeout next) = Wait timeout (f next)
fmap f (Read uri next) = Read uri (f next)
type Action = Free ActionFunctor
data MajorFunctor next = Log LogText next
| Act Action next
| Send Message
instance Functor MajorFunctor where
fmap f (Log text next) = Log text (f next)
fmap f (Act action next) = Act action (f next)
fmap f (Send message) = Send message
type Major = Free MajorFunctor
问题是,GHC 会抱怨inMajorFunctor
是一种,而不仅仅是一种类型。这是因为在定义中它应该接受 a作为类型参数,而在该行中它不包含这样的参数。但是即使消息对我来说很清楚,我也不确定是否应该在仿函数中声明这样的额外类型参数:Action
Act Action next
(* -> *)
data ActionFunctor
next
Act Action
Major
data MajorFunctor actionNext next = ...
这看起来很奇怪,因为只有一个数据构造函数会使用该参数,而这样的暴露会变成每一个MajorFunctor
,MajorFunctor actionNext
看起来完全暴露了太多细节。所以我看了一下FreeT
transformer,看看它是否是我想要的。但是,在我的情况下,我只需要Action
在 DSL 程序有这样的操作时调用解释器,而不是bind
单子程序中的每一个,所以我也不确定转换器是否是一个好的解决方案。