用Coq的功能编程语言如何编写else语句?

时间:2019-01-21 23:23:44

标签: coq

我试图计算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语句非常相似。因此,或者我错过了函数式编程的要点或其他东西。我猜这是我担心的主要问题。

2 个答案:

答案 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值与truefalse进行匹配,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语句与nilh :: t1匹配(这是cons h t1或类似的符号,具体取决于bag的定义) 。在匹配语句中

match n with
| 0 => (* something *)
| S n => (* something else *)
end.

我们在nat0S _的构造函数上进行匹配。

在原始代码中,您尝试在不是构造函数的v上进行匹配,因此Coq只需绑定一个新变量并将其命名为v