将随意列表转换为Coq中的依赖类型列表

问题描述 投票:3回答:1

我在Coq中有以下列表定义:

Variable A : Set.
Variable P : A -> Prop.
Hypothesis P_dec : forall x, {P x}+{~(P x)}.

Inductive plist : nat -> Set :=
   pnil : plist O
  | pcons : A -> forall n, plist n -> plist n
  | pconsp : forall (a:A) n, plist n -> P a -> plist (S n)
  .

它描述了“A类型的元素列表,其中至少n满足谓词P”。

我的任务是创建将随意列表转换为plist的函数(最大可能的n)。我的尝试是首先计算与P匹配的所有元素,然后根据结果设置输出类型:

Fixpoint pcount (l : list A) : nat :=
  match l with
  | nil => O
  | h::t => if P_dec h then S(pcount t) else pcount t
  end.

Fixpoint plistIn (l : list A) : (plist (pcount l)) :=
  match l with
  | nil => pnil
  | h::t => match P_dec h with
          | left proof => pconsp h _ (plistIn t) proof
          | right _ => pcons h _ (plistIn t) 
          end
  end.

但是,我在使用left proof时遇到错误:

Error:
In environment
A : Set
P : A -> Prop
P_dec : forall x : A, {P x} + {~ P x}
plistIn : forall l : list A, plist (pcount l)
l : list A
h : A
t : list A
proof : P h
The term "pconsp h (pcount t) (plistIn t) proof" has type
 "plist (S (pcount t))" while it is expected to have type
 "plist (pcount (h :: t))".

问题是Coq无法看到S (pcount t)等于pcount (h :: t)知道P h,已经证明了。我不能让Coq知道这个道理。

如何正确定义此功能?甚至可以这样做吗?

coq dependent-type
1个回答
5
投票

您可以使用依赖模式匹配,因为结果类型plist (pcount (h :: t))取决于P_dec hleft还是right

下面,关键字as引入了一个新变量preturn告诉整个match表达式的类型,由p参数化。

Fixpoint plistIn (l : list A) : (plist (pcount l)) :=
  match l with
  | nil => pnil
  | h::t => match P_dec h as p return plist (if p then _ else _) with
          | left proof => pconsp h (pcount t) (plistIn t) proof
          | right _ => pcons h _ (plistIn t) 
          end
  end.

当用plist (if p then _ else _)代替时,plist (pcount (h :: t))的类型必须等于p := P_dec h。然后在每个分支,比如说left proof,你需要产生plist (if left proof then _ else _)(它减少到左分支)。

Coq可以推断出下划线中的内容有点神奇,但为了安全起见,你总能把它拼出来:if p then S (pcount t) else pcount t(这意味着与pcount的定义完全匹配)。

© www.soinside.com 2019 - 2024. All rights reserved.