简体   繁体   English

Hasfell的multirec软件包中的“ HFix”如何工作?

[英]How does `HFix` work in Haskell's multirec package?

I understand the regular fixed-point type combinator and I think I understand the higher-order fixed-n type combinators, but HFix eludes me. 我了解常规定点类型组合器,并且我了解高阶定n型组合器,但是HFixHFix Could you give an example of a set of data-types and their (manually derived) fixed points that you can apply HFix to. 您能否举一个可以应用HFix的数据类型及其固定点的HFix

The natural reference is the paper Generic programming with fixed points for mutually recursive datatypes where the multirec package is explained. 自然的参考是针对互递数据类型的具有固定点的通用编程,其中解释了multirec包

HFix is a fixpoint type combinator for mutually recursive data types. HFix是用于相互递归数据类型的固定点类型组合器。 It is well explained in Section 3.2 in the paper, but the idea is to generalise this pattern: 本文在第3.2节中对此进行了很好的解释,但是我们的想法是概括这种模式:

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

to

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

To restrict how many types it does a fixed point over, they use type constructors instead of *^n. 为了限制执行固定点操作的类型,它们使用类型构造函数而不是* ^ n。 They give an example of an AST data type, mutually recursive over three types in the paper. 他们给出了一个AST数据类型的示例,该数据在本文的三种类型之间相互递归。 I offer you perhaps the simplest example instead. 我也许会为您提供最简单的示例。 Let us HFix this data type: 让我们HFix这种数据类型:

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

Let us introduce the family specific GADT for this datatype as is done in section 4.1 让我们介绍该数据类型的特定于家庭的GADT,如第4.1节所述

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

EO Even will mean that we are carrying around an even number. EO Even表示我们携带的是偶数。 We need El instances for this to work, which says which specific constructor we are refering to when writing EO Even and EO Odd respectively. 我们需要El实例才能正常工作,它表示在编写EO EvenEO Odd分别引用的是哪个特定的构造函数。

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

These are used as constraints for the HFunctor instance for I . 这些用作IHFunctor实例的约束。

Let us now define the pattern functor for the even and odd data type. 现在让我们为偶数和奇数数据类型定义模式函子。 We use the combinators from the library. 我们使用库中的组合器。 The :>: type constructor tags a value with its type index: :>:类型构造函数使用类型索引标记值:

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

Now we can use HFix to tie the knot around this pattern functor: 现在我们可以使用HFix来围绕此模式函子打结:

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

These are now isomorphic to EO Even and EO Odd, and we can use the hfrom and hto functions if we make it an instance of Fam : 这些现在与EO Even和EO Odd同构,并且如果将其hto Fam的实例,则可以使用hfromhto函数

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

A simple little test: 一个简单的小测试:

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

test' :: Even
test' = hto E test

*HFix> test'
ESucc (OSucc Zero)

Another silly test with an Algebra turning Even and Odd s to their Int value: 另一项愚蠢的测试,即代数将EvenOddInt值:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM