5

我了解常规定点类型组合器,并且我认为我了解高阶定点类型组合器,但HFix我却不知道。您能否举一个您可以应用的一组数据类型及其(手动派生的)固定点的示例HFix

4

1 回答 1

5

自然参考是论文Generic programming with fixed points for interrecursive datatypes ,其中解释了multirec 包

HFix是相互递归数据类型的定点类型组合器。论文第 3.2 节对此进行了很好的解释,但其想法是概括这种模式:

 Fix :: (∗ -> ∗) -> ∗
 Fix2 :: (∗ -> ∗ -> ∗) -> (∗ -> ∗ -> ∗) -> ∗

 Fixn :: ((∗ ->)^n * ->)^n ∗
 ≈
 Fixn :: (*^n -> *)^n -> *

为了限制它对固定点的类型数量,他们使用类型构造函数而不是 *^n。他们给出了一个 AST 数据类型的例子,论文中的三种类型相互递归。我给你也许是最简单的例子。让我们HFFix这个数据类型:

data Even = Zero | ESucc Odd deriving (Show,Eq)
data Odd  = OSucc Even       deriving (Show,Eq)

让我们像第 4.1 节中所做的那样介绍该数据类型的系列特定 GADT

data EO :: * -> * where
  E :: EO Even
  O :: EO Odd

EO Even将意味着我们携带一个偶数。我们需要 El 实例才能使其工作,它说明了我们在编写时分别引用了哪个特定的构造EO Even函数EO Odd

instance El EO Even where proof = E
instance El EO Odd  where proof = O

这些用作 I实例HFunctor约束。

现在让我们为偶数和奇数数据类型定义模式函子。我们使用库中的组合器。类型构造函数用它的:>:类型索引标记一个值:

type PFEO = U      :>: Even   -- ≈ Zero  :: ()      -> EO Even
        :+: I Odd  :>: Even   -- ≈ ESucc :: EO Odd  -> EO Even
        :+: I Even :>: Odd    -- ≈ OSucc :: EO Even -> EO Odd

现在我们可以用HFix这个模式函子来打结:

type Even' = HFix PFEO Even
type Odd'  = HFix PFEO Odd

这些现在与 EO Even 和 EO Odd 同构, 如果我们将其设为 的实例,我们可以使用hfromandhto函数Fam

type instance PF EO = PFEO

instance Fam EO where
  from E Zero      = L    (Tag U)
  from E (ESucc o) = R (L (Tag (I (I0 o))))
  from O (OSucc e) = R (R (Tag (I (I0 e))))
  to   E (L    (Tag U))           = Zero
  to   E (R (L (Tag (I (I0 o))))) = ESucc o
  to   O (R (R (Tag (I (I0 e))))) = OSucc e

一个简单的小测试:

test :: Even'
test = hfrom E (ESucc (OSucc Zero))

test' :: Even
test' = hto E test

*HFix> test'
ESucc (OSucc Zero)

另一个用代数转向EvenOddsInt值的愚蠢测试:

newtype Const a b = Const { unConst :: a }

valueAlg :: Algebra EO (Const Int)
valueAlg _ = tag (\U             -> Const 0)
           & tag (\(I (Const x)) -> Const (succ x))
           & tag (\(I (Const x)) -> Const (succ x))

value :: Even -> Int
value = unConst . fold valueAlg E
于 2012-03-15T20:56:48.593 回答