如何基于免费的 monad 编写 DSL?
How to write a DSL based on free monad?
我正在玩 Haskell 中的自由 monad,但我在自由 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 作为接受操作的函数和 returns 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))
我正在玩 Haskell 中的自由 monad,但我在自由 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 作为接受操作的函数和 returns 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))