【问题标题】:How does `HFix` work in Haskell's multirec package?`HFix` 在 Haskell 的 multirec 包中是如何工作的?
【发布时间】:2012-04-01 07:39:27
【问题描述】:

我了解常规定点类型组合器,我想我了解高阶定点类型组合器,但 HFix 让我无法理解。您能否举例说明一组数据类型及其(手动派生的)固定点,您可以将HFix 应用于这些固定点。

【问题讨论】:

    标签: haskell types generic-programming multirec


    【解决方案1】:

    自然参考是论文Generic programming with fixed points for mutually recursive datatypes multirec package 解释的地方。

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

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

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

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

    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 EvenEO Odd时分别指的是。

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

    这些用作HFunctor instance 的约束 为I

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

    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 同构,我们可以使用 hfrom and hto functions 如果我们让它成为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)
    

    另一个用代数将EvenOdds 转换为Int 值的愚蠢测试:

    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
    

    【讨论】:

    • 谢谢,阅读本文对您有所帮助,但我还是有点困惑。你介意在:>: 上更详细地介绍一下吗,它对我来说仍然很不透明。
    • 是的,它是一个相当复杂的库。我添加了一个关于它的小评论,现在没有更多时间了。干杯!
    • 花了一点时间,但是在阅读了一遍又一遍之后,API 文档和论文,它终于开始变得有意义了。非常感谢,你帮了很多忙。
    猜你喜欢
    • 2012-09-08
    • 2016-12-06
    • 2011-04-21
    • 2012-04-23
    • 1970-01-01
    • 2015-04-02
    • 2016-09-16
    • 2017-11-27
    相关资源
    最近更新 更多