我在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))".
问题是,知道已经证明的S (pcount t)
时,Coq无法看到pcount (h :: t)
等于P h
。我不能让Coq知道这个事实。
如何正确定义此功能?甚至有可能这样做吗?
答案 0 :(得分:5)
您可以使用依赖模式匹配,因为结果类型plist (pcount (h :: t))
取决于P_dec h
是left
还是right
。
下面,关键字as
引入了一个新变量p
,而return
告诉了整个match
表达式的类型,该表达式由p
参数化。 / 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
的定义完全匹配)