9

我正在尝试使用 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?

4

1 回答 1

9

让它变得简单

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

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

这应该可以帮助您了解始终使用TunT无处不在,而不是仅在其他级别。

让它变得复杂

Both Freeand TermFhave kind (*->*)->(*->*),这是一种变压器。您正在寻找 和 的组成的不动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 . unFixT您将使用的任何地方使用unT

于 2014-12-12T01:24:02.677 回答