【问题标题】:Infinite recursive types in Coq (for Bananas and Lenses)Coq 中的无限递归类型(用于 Bananas 和 Lenses)
【发布时间】:2019-09-09 07:45:14
【问题描述】:

我希望看到 Coq 版本的 Bananas、Lenses 等。它们是在 sumtypeofway Introduction to Recursion schemes 的优秀系列博文中建立的

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

具体来说,定义取决于类型

newtype Term f = In { out :: f (Term f) }

构建无限类型f (f (f (f ...)))Term f 允许使用 Term 类型族对变形、变形、变形等进行非常漂亮和简洁的定义。

尝试将其移植到 Coq

Inductive Term f : Type := {out:f (Term f)}.

给了我预期的

Error: Non strictly positive occurrence of "Term" in "f (Term f) -> Term f".

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

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

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

【问题讨论】:

    标签: coq recursion-schemes


    【解决方案1】:

    我认为流行的解决方案是将函子编码为"containers",这篇论文的介绍是一个很好的起点:https://arxiv.org/pdf/1805.08059.pdf 这个想法要老得多(论文的意思是给出一个独立的解释),并且你可以从那篇论文中寻找参考资料,但如果你不熟悉类型论或范畴论,我在粗略搜索中发现的内容可能很难理解。

    简而言之,我们使用以下类型而不是Type -> Type

    Set Implicit Arguments.
    Set Contextual Implicit.
    
    Record container : Type := {
      shape : Type;
      pos : shape -> Type;
    }.
    

    如果你想象一个递归类型的“基本函子”F Fix F,那么大致在哪里,shape 描述了 F 的构造函数,对于每个构造函数,pos 枚举了它。所以List的基函子

    data ListF a x
      = NilF       -- no holes
      | ConsF a x  -- one hole x
    

    由这个容器给出:

    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;
    |}.
    

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

    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).
    

    所以除了Fix f = f (Fix f),fixpoint 构造可以使用一个容器:

    Inductive Fix (c : container) : Type := MkFix : ext c (Fix c) -> Fix c.
    

    并非所有函子都可以编码为容器(延续函子就是一个很好的例子),但您不会经常看到它们与 Fix 一起使用。

    完整要点:https://gist.github.com/Lysxia/21dd5fc7b79ced410b129f31ddf25c12

    【讨论】:

    • 你使用哪个版本的 Coq?我无法喂饱Inductive ext ...。我正在使用 8.9.1。
    • 对不起,我只是把它直接写到 SO 中,没有尝试编译它。 a 应该是类似c 的参数。
    • 谢谢你 - 我已经尝试阅读这个,但你能否展示一个将如何实现,即fmap,它在容器而不是任意函子上运行?我没有设法做到这一点......
    • 好的,我现在有一个fmap 的版本,但我必须将list_shape 更改为ConsF 有两个孔(我需要一个孔让尾部能够递归) .无论如何,我认为您的答案是要走的路,所以我会将其标记为已接受。感谢您的快速回答和清晰的解释。我可能会在此处添加一个指向要点的链接,以供(我自己的)参考。
    猜你喜欢
    • 2012-12-10
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    • 2022-05-10
    • 1970-01-01
    • 2018-07-29
    • 2012-01-08
    • 1970-01-01
    相关资源
    最近更新 更多