我试图计算Coq中v
中元素natlist/bag
的出现次数。我尝试过:
Fixpoint count (v:nat) (s:bag) : nat :=
match s with
| nil => 0
| h :: tl => match h with
| v => 1 + (count v tl)
end
end.
但是我的证明不起作用:
Example test_count1: count 1 [1;2;3;1;4;1] = 3.
Proof. simpl. reflexivity. Qed.
为什么第一段代码不起作用? v
不匹配怎么办?
我也尝试过:
Fixpoint count (v:nat) (s:bag) : nat :=
match s with
| nil => 0
| h :: tl => match h with
| v => 1 + (count v tl)
| _ => count v tl
end
end.
但是这也会在Coq中给出一个错误,我什至无法运行它。
函数式编程对我来说是一种新事物,所以我不知道该如何在Coq中实际表达这一点。我真的只想说h
是否匹配v
,然后执行+1并递归,否则仅递归(即我想加零)。
有没有一种简单的方法可以用Coq的函数式编程语言来表达这一点?
我问的原因是因为在我看来,匹配项与“常规” Python编程中的if else语句非常相似。因此,或者我错过了函数式编程的要点或其他东西。我猜这是我担心的主要问题。
答案 0 :(得分:2)
您尝试编写的match
语句实际上只是用新变量v
遮盖了v
变量,该变量也只包含h
的副本。
为了测试两个自然数是否相等,可以使用Nat.eqb
返回一个bool
值,然后可以将其与以下值进行匹配:
Require Import Arith.
Fixpoint count (v:nat) (s:bag) : nat :=
match s with
| nil => 0
| h :: tl => match Nat.eqb v h with
| true => 1 + (count v tl)
| false => count v tl
end
end.
碰巧,为了将bool
值与true
或false
进行匹配,Coq还以功能if
/ {{1}的形式提供了语法糖。 }构造函数(如果您熟悉其中的一种,则非常类似于C或C ++中的三元else
运算符):
?:
(实际上,碰巧Require Import Arith.
Fixpoint count (v:nat) (s:bag) : nat :=
match s with
| nil => 0
| h :: tl => if Nat.eqb v h then
1 + (count v tl)
else
count v tl
end.
可以使用具有两个构造函数的任何归纳类型:然后第一个构造函数转到if
分支,第二个构造函数转到if
分支但是,else
类型将list
作为其第一个构造函数,并将nil
作为其第二个构造函数:因此,即使从技术上讲,您可以编写一个{{ 1}}来测试是否为空或非空,它最终会与您预期的工作方式相反。)
但是,一般而言,对于泛型类型,不一定有一种方法来确定该类型的两个成员是否相等,因为对于cons
来说,if
。因此,如果您想编写一个list
的概括,该概括可能适用于更通用的类型,则必须采用一个指定相等性决定过程的参数。
答案 1 :(得分:2)
(这与Daniel的回答类似,但是我已经写了大部分)
您的问题是这段代码中
:match h with
| v => 1 + (count v tl)
end
与v
匹配将绑定 new 变量v
。要测试h
是否等于v
,您必须使用某种决策过程来测试自然数的相等性。
例如,您可以使用Nat.eqb
,它接受两个自然数并返回一个bool
,指示它们是否相等。
Require Import Nat.
Fixpoint count (v:nat) (s:bag) : nat :=
match s with
| nil => 0
| h :: tl => if (eqb h v) then (1 + count v t1) else (count v t1)
end.
为什么我们不能简单地匹配我们想要的术语?模式匹配始终在类型的构造函数上匹配。在这段代码中,外部match语句与nil
和h :: t1
匹配(这是cons h t1
或类似的符号,具体取决于bag
的定义) 。在匹配语句中
match n with
| 0 => (* something *)
| S n => (* something else *)
end.
我们在nat
:0
和S _
的构造函数上进行匹配。
在原始代码中,您尝试在不是构造函数的v
上进行匹配,因此Coq只需绑定一个新变量并将其命名为v
。