我正在尝试使用带有列表的构造函数定义数据类型,并包含有关此列表的命题。
这很好用:
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
中使用普通列表,并且仍然包含有关该列表的命题?
答案 0 :(得分:3)
我认为不幸的是,没有一种方法可以直接在定义中包含该约束。我看到前进的两条道路:
更改mkFoo
的定义,以便将列表的头部作为附加参数:
mkFoo : Foo -> list Foo -> Foo
无限制地定义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为这种结构提供了很好的支持。