如何编写基于自由monad的DSL



我在Haskell中玩自由monads,我被困在定义在Free monad中提升函子构造函数的函数上。

我将 AppF 函子作为几个函子的总和,每个函子代表一个效果。其中一个函子是 DbTrF,表示数据库事务效应。

所以我的 AppF 定义如下:

data AppF a = 
  DbTr (DbTrF a)
  | ... functors for the other types of effects
  deriving (Functor)

我的 DbTrF 定义如下:

data Op i r =
  Get i
  | Insert i r
  | Delete i
  | Update i (r -> r)
data DbTrF a =
  UserTb (Op UserId UserData) (Maybe UserData -> a)
  | SessionTb (Op SessionId SessionData) (Maybe SessionData -> a)
  | ... here is the code for other tables
  deriving(Functor)

那么我想要一个交易函数

transact :: Table i r t-> Op i r -> AppM (Maybe r)

。我想像这样使用:

transactExample = transact UserTb (Get someUserId)

为此,我想引入 Table 类型作为接受操作并返回 DbTrF 值的函数:

newtype Table i r a = Table {tbId :: Op i r -> (Maybe r -> a) -> DbTrF a}

我的尝试是这样的:

transact (Table tb) op = liftF (DbTr (tb op ???))

但我不确定要放什么而不是问号。

这是一个好的方向还是我做错了?

谢谢!

让我们尝试逐步实例化函数的主体,在剩余的孔中跟踪预期的类型:

transact :: Table i r a -> Op i r -> AppM (Maybe r)
transact (Table tb) op
  = ??? :: AppM (Maybe r)
  = liftF (??? :: AppF (Maybe r))
  = liftF (DbTr (??? :: DbTrF (Maybe r)))
  = liftF (DbTr (tb op (??? :: Maybe r -> Maybe r))

但是,从Table tb的类型来看,我们也有tb :: Op i r -> (Maybe r -> a) -> DbTrF a.因此a ~ Maybe r,我们可以用id来解决上面的漏洞,只需对transact类型稍作改变。

transact :: Table i r (Maybe r) -> Op i r -> AppM (Maybe r)
transact (Table tb) op = liftF (DbTr (tb op id))

最新更新