Coq 中的无限递归类型(用于 Bananas 和 Lenses)

lar*_*rsr 6 coq recursion-schemes

我想看一个 Coq 版本的 Bananas、Lenses 等。它们建立在sumtypeofway 递归方案介绍的优秀系列博客文章中

然而,博客文章是在 Haskell 中,它允许无限的非终止递归,因此完全满足于Y组合器。哪个 Coq 不是。

特别是,定义取决于类型

newtype Term f = In { out :: f (Term f) }
Run Code Online (Sandbox Code Playgroud)

它构建无限类型 f (f (f (f ...)))Term f 允许使用 Term 系列类型对 catamorphisms、paramorphisms、anamorphisms 等进行非常漂亮和简洁的定义。

尝试将其移植到 Coq 作为

Inductive Term f : Type := {out:f (Term f)}.
Run Code Online (Sandbox Code Playgroud)

给了我预期的

Error: Non strictly positive occurrence of "Term" in "f (Term f) -> Term f".
Run Code Online (Sandbox Code Playgroud)

问:在 Coq 中将上述 Haskell Term 类型形式化的好方法是什么?

以上f是 type Type->Type,但也许它太笼统了,可能有某种方法将我们限制为归纳类型,使得每个应用程序都f在减少?

也许有人已经在 Coq 中实现了Banans、Lenses、Envelopes的递归方案?

Li-*_*Xia 4

我认为流行的解决方案是将函子编码为“容器”,本文的介绍是一个很好的起点:https ://arxiv.org/pdf/1805.08059.pdf这个想法很古老(论文的意思是给出一个独立的解释),您可以从该论文中查找参考文献,但是如果您不熟悉类型论或范畴论,我在粗略搜索中发现的内容可能很难理解。

简而言之,Type -> Type我们使用以下类型代替 :

Set Implicit Arguments.
Set Contextual Implicit.

Record container : Type := {
  shape : Type;
  pos : shape -> Type;
}.
Run Code Online (Sandbox Code Playgroud)

粗略地说,如果您想象一个F递归类型的“基本函子” Fix Fshape则描述 的构造函数F,并为每个构造函数pos枚举其中的“漏洞”。所以基函子为List

data ListF a x
  = NilF       -- no holes
  | ConsF a x  -- one hole x
Run Code Online (Sandbox Code Playgroud)

由该容器给出:

Inductive list_shape a :=
  | NilF : list_shape a
  | ConsF : a -> list_shape a.

Definition list_pos a (s : list_shape a) : Type :=
  match s with
  | NilF    => False (* no holes *)
  | ConsF _ => True  (* one hole x *)
  end.

Definition list_container a : container := {|
  shape := list_shape a;
  pos := fun s => list_pos s;
|}.
Run Code Online (Sandbox Code Playgroud)

关键是这个容器描述了一个严格的正函子:

Inductive ext (c : container) (a : Type) : Type := {
  this_shape : shape c;
  this_rec : pos c this_shape -> a;
}.

Definition listF a : Type -> Type := ext (list_container a).
Run Code Online (Sandbox Code Playgroud)

因此Fix f = f (Fix f),不动点构造可以采用容器来代替 :

Inductive Fix (c : container) : Type := MkFix : ext c (Fix c) -> Fix c.
Run Code Online (Sandbox Code Playgroud)

并非所有函子都可以编码为容器(延续函子就是一个主要例子),但您不经常看到它们与Fix.

完整要点:https://gist.github.com/Lysxia/21dd5fc7b79ced4 ​​10b129f31ddf25c12