在Coq';s函数式编程语言?

在Coq';s函数式编程语言?,coq,Coq,我试图计算Coq中natlist/bag中元素v的出现次数。我试过: 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:

我试图计算Coq中
natlist/bag
中元素
v
的出现次数。我试过:

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
,那么执行a+1递归,否则只递归(即,我猜加零)

有没有一种简单的方法可以用Coq的函数式编程语言来表达这一点


我之所以问这个问题,是因为我觉得match与“普通”Python编程中的if-else语句非常相似。因此,要么我错过了函数式编程的要点,要么是什么。这是我所关心的主要问题,我想是隐式的。

您试图编写的
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.
<> P> > <代码> BoOL 值与<代码>真< /代码>或<代码>伪< /代码>,Coq也提供了函数-<代码>的语法糖> < < /Calp>/Cuth> Ethue/Cuth>构造(这非常像三元<代码>:< /Cord> C或C++的运算符,如果你熟悉其中任一个):

(实际上,
if
与任何归纳类型一起工作时正好有两个构造函数:然后第一个构造函数转到
if
分支,第二个构造函数转到
else
分支。然而,
list
类型的第一个构造函数是
nil
,第二个构造函数是
cons
构造函数:因此,即使从技术上讲,您可以编写一个包含
列表的
if
语句来测试空性或非空性,它最终也会与您可能期望的工作方式相反。)


但是,一般来说,对于泛型类型,不一定有一种方法来决定该类型的两个成员是否相等,因为在
Nat
的情况下有
Nat.eqb
。因此,如果您想编写一个可以适用于更一般类型的
count
的泛化,您必须接受一个argument指定相等决策过程。

您试图编写的
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.
<> P> > <代码> BoOL 值与<代码>真< /代码>或<代码>伪< /代码>,Coq也提供了函数-<代码>的语法糖> < < /Calp>/Cuth> Ethue/Cuth>构造(这非常像三元<代码>:< /Cord> C或C++的运算符,如果你熟悉其中任一个):

(实际上,
if
与任何归纳类型一起工作时正好有两个构造函数:然后第一个构造函数转到
if
分支,第二个构造函数转到
else
分支。然而,
list
类型的第一个构造函数是
nil
,第二个构造函数是
cons
构造函数:因此,即使从技术上讲,您可以编写一个包含
列表的
if
语句来测试空性或非空性,它最终也会与您可能期望的工作方式相反。)

但是,一般来说,对于泛型类型,不一定有一种方法来决定该类型的两个成员是否相等,因为在
Nat
的情况下有
Nat.eqb
。因此,如果您想编写一个可以适用于更一般类型的
count
的泛化,您必须接受一个argument指定平等决策程序。

(这与Daniel的答案类似,但我已经写了大部分)

您的问题是,在此代码中:

match h with
| v => 1 + (count v tl)
end
v
匹配将绑定一个新变量
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.
为什么我们不能简单地匹配我们想要的术语呢?模式匹配总是匹配类型的构造函数。在这段代码中,外部匹配语句匹配
nil
h::t1
(这是
cons h t1
或类似的符号,取决于
bag
的精确定义).在匹配语句中,如

match n with
| 0 => (* something *)
| S n => (* something else *)
end.
我们在
nat
的构造函数上进行匹配:
0
S

在原始代码中,您尝试匹配
v
,它不是构造函数,因此Coq只需绑定一个新变量并调用它
v

(这与Daniel的答案类似,但我已经编写了大部分)

您的问题是,在此代码中:

match h with
| v => 1 + (count v tl)
end
v
匹配将绑定一个新变量
v
。要测试
h
是否等于
v
,必须使用一些决策过程来测试自然数的相等性

例如,您可以使用
Nat.eqb
,它接受两个自然数并返回一个表示w的
bool