由于多态性功能导致的非阳性发生

时间:2018-05-07 20:56:12

标签: coq algebraic-data-types

我正在尝试使用带有列表的构造函数定义数据类型,并包含有关此列表的命题。

这很好用:

Require Import Coq.Lists.List.
Import ListNotations.

Inductive Foo :=  MkFoo : list Foo -> Foo.

这样做:

Inductive Foo :=  MkFoo : forall (l : list Foo), Foo.

但这失败了

Inductive Foo :=  MkFoo : forall (l : list Foo), l <> [] -> Foo.

Non strictly positive occurrence of "Foo"
in "forall l : list Foo, l <> [] -> Foo".

我认为这是因为[]实际上是@nil Foo而Coq不喜欢Foo的这种情况。

我目前正在使用vector来解决这个问题,就像这样

Require Import Coq.Vectors.Vector.

Inductive Foo :=  MkFoo : forall n (l : Vector.t Foo n), n <> 0 -> Foo.

但由于在Coq中使用依赖数据结构而出现的复杂情况让我感到奇怪:

有没有办法可以在MkFoo中使用普通列表,并且仍然包含有关该列表的命题?

1 个答案:

答案 0 :(得分:3)

我认为不幸的是,没有一种方法可以直接在定义中包含该约束。我看到前进的两条道路:

  1. 更改mkFoo的定义,以便将列表的头部作为附加参数:

    mkFoo : Foo -> list Foo -> Foo
    
  2. 无限制地定义Foo,并定义一个单独的格式良好的谓词:

    Require Import Coq.Lists.List.
    
    Inductive Foo := mkFoo : list Foo -> Foo.
    
    Definition isEmpty {T : Type} (x : list T) :=
      match x with
      | nil => true
      | _   => false
      end.
    
    Fixpoint wfFoo (x : Foo) : Foo :=
      match x with
      | mkFoo xs => negb (isEmpty xs) && forallb wfFoo xs
      end.
    

    然后,您可以显示您关注的Foo上的所有功能wfFoo。也可以使用子集类型将Foo的成员打包为wfFoo的证明,从而保证Foo的客户端永远不必触及不正确的元素。由于wfFoo被定义为布尔属性,因此等式wfFoo x = true与证明无关,这可以保证类型{ x : Foo | wfFoo x = true }表现良好。 Mathematical Components library为这种结构提供了很好的支持。