语法树:free monad + Bound.Scope

时间:2014-12-12 00:00:38

标签: haskell abstract-syntax-tree free-monad

我尝试使用ekmett的库boundfree来定义抽象语法类型。我有一些工作,我可以删除以下最小的例子:

{-# LANGUAGE DeriveFunctor #-}

import Bound
import Control.Monad.Free

type Id = String

data TermF f α =
    AppF α α
  | BindF Id (Scope () f α)
  deriving Functor

newtype Term' α = T {unT :: Free (TermF Term) α}
type Term = Free (TermF Term')

最后两行是,呃,不是我所希望的。它们使得PITA实际上可以利用开放递归进行注释(或其他)。

有没有更好的方法将这两个库结合使用,和/或我应该放弃尝试让Term成为免费的monad?

1 个答案:

答案 0 :(得分:9)

简单

您可以将最后两行简化为。

newtype Term α = T {unT :: Free (TermF Term) α}

这应该可以帮助您在任何地方始终使用TunT,而不是仅在其他所有级别使用。{/ p>

使其复杂化

FreeTermF都有类型(*->*)->(*->*),这是一种变换器。您正在寻找FreeTermF组成的固定点。我们可以编写一般的变压器组成。

{-# LANGUAGE PolyKinds #-}

newtype ComposeT g h f a = ComposeT { unComposeT :: g (h f) a}
    deriving Functor

我们也可以编写变压器的固定点。

{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}

newtype FixT t a = FixT { unFixT :: t (FixT t) a }

deriving instance Functor (t (FixT t)) => Functor (FixT t)

然后你可以写

type Term = FixT (ComposeT Free TermF)

然后在您使用FixT . ComposeT的任何地方使用T到处使用unComposeT . unFixTunT