【Coq】17 Poly III 附加练习

附加练习 Additional Exercises

57: 2 stars, standard (fold_length)

列表上的许多常见功能可以按折叠方式实现。例如,以下是长度的替代定义:

Definition fold_length {X : Type} (l : list X) : nat :=
  fold (fun _ n => S n) l 0.

Example test_fold_length1 : fold_length [4;7;0] = 3.
Proof. reflexivity. Qed.

证明折叠长度的正确性。(提示:了解自反性比siml更积极地简化表达式可能会有所帮助——也就是说,您可能会发现siml什么都不做,但自反性解决了目标。)

Theorem fold_length_correct : forall X (l : list X),
  fold_length l = length l.
Proof.
(* FILL IN HERE *) Admitted.

58: 3 stars, standard (fold_map)

我们也可以用fold来定义map。完成下面的fold_map。

Definition fold_map {X Y: Type} (f: X -> Y) (l: list X) : list Y
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.

写下一个定理fold_map_correct,说明fold_map是正确的,并证明它。(提示:再一次,请记住,自反性比siml更积极地简化表达式。)

(* FILL IN HERE *)

(* Do not modify the following line: *)
Definition manual_grade_for_fold_map : option (nat*string) := None.

59: 2 stars, advanced (currying)

在Coq中,函数f:a→ B→ C真的有 A → (B → C)类型 。也就是说,如果你给f一个类型为a的值,它会给你函数f':B→ C.如果你给f'一个类型为B的值,它将返回类型为C的值。这允许部分应用,如plus3。为纪念逻辑学家Haskell Curry,使用返回函数的函数处理参数列表被称为Curry。

相反,我们可以重新解释A→ B→ C类型为(A × B) → C 这叫做uncurrying。对于无载波二进制函数,两个参数必须同时成对给出;没有部分应用程序。

我们可以对currying的定义如下:

Definition prod_curry {X Y Z : Type}
  (f : X * Y -> Z) (x : X) (y : Y) : Z := f (x, y).

作为一种练习,定义它的相反方向,即“prod_uncurry”。然后证明下面的定理,证明这两个定理是相反的。

Definition prod_uncurry {X Y Z : Type}
  (f : X -> Y -> Z) (p : X * Y) : Z
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.

作为currying有用性的一个(微不足道的)例子,我们可以用它来缩短我们上面看到的一个例子:

Example test_map1': map (plus 3) [2;0;2] = [5;3;5].
Proof. reflexivity. Qed.

思考练习:在运行以下命令之前,您能否计算prod_curry和prod_uncurry的类型?

Check @prod_curry.
Check @prod_uncurry.

Theorem uncurry_curry : forall (X Y Z : Type)
                        (f : X -> Y -> Z)
                        x y,
  prod_curry (prod_uncurry f) x y = f x y.
Proof.
  (* FILL IN HERE *) Admitted.

Theorem curry_uncurry : forall (X Y Z : Type)
                        (f : (X * Y) -> Z) (p : X * Y),
  prod_uncurry (prod_curry f) p = f p.
Proof.
  (* FILL IN HERE *) Admitted.

60: 2 stars, advanced (nth_error_informal)

回想一下 nth_error函数的定义:

Fixpoint nth_error {X : Type} (l : list X) (n : nat) : option X :=
     match l with
     | [] => None
     | a :: l' => if n =? O then Some a else nth_error l' (pred n)
     end.

写出以下定理的非正式证明:

forall X l n, length l = n -> @nth_error X l n = None

(* FILL IN HERE *)
(* Do not modify the following line: *)
Definition manual_grade_for_informal_proof : option (nat*string) := None.

下面的练习探索定义自然数的另一种方法,使用以数学家阿隆佐·丘奇命名的所谓丘奇数字。我们可以将一个自然数n表示为一个函数,该函数将函数f作为参数,并返回迭代n次的f。

Module Church.
Definition cnat := forall X : Type, (X -> X) -> X -> X.

让我们看看如何用这个符号写一些数字。对函数进行一次迭代应该与仅应用它相同。因此:

Definition one : cnat :=
  fun (X : Type) (f : X -> X) (x : X) => f x.

同样地,[two]应该对其论点应用[f]两次:

Definition two : cnat :=
  fun (X : Type) (f : X -> X) (x : X) => f (f x).

定义[zero]有点棘手:我们如何“应用函数零次”?答案其实很简单:只需原封不动地返回参数。

Definition zero : cnat :=
  fun (X : Type) (f : X -> X) (x : X) => x.

更一般地说,数字n可以写成fun X f x ⇒ f (f ... (f x) ...),其中f出现n次。请特别注意,我们前面定义的doit3times函数实际上只是3的教堂表示。

Definition three : cnat := @doit3times.

完成以下函数的定义。通过自反性证明相应的单元测试,确保它们通过。

61: 1 star, advanced (church_succ)

自然数的后继数:给定一个教会数字n,后继数succ n是一个将其参数迭代一次超过n的函数。

Definition succ (n : cnat) : cnat
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.

Example succ_1 : succ zero = one.
Proof. (* FILL IN HERE *) Admitted.

Example succ_2 : succ one = two.
Proof. (* FILL IN HERE *) Admitted.

Example succ_3 : succ two = three.
Proof. (* FILL IN HERE *) Admitted.

62: 1 star, advanced (church_plus)

两个自然数相加:

Definition plus (n m : cnat) : cnat
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.

Example plus_1 : plus zero one = one.
Proof. (* FILL IN HERE *) Admitted.

Example plus_2 : plus two three = plus three two.
Proof. (* FILL IN HERE *) Admitted.

Example plus_3 :
  plus (plus two two) three = plus one (plus three three).
Proof. (* FILL IN HERE *) Admitted.

63: 2 stars, advanced (church_mult)

乘法:

Definition mult (n m : cnat) : cnat
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.

Example mult_1 : mult one one = one.
Proof. (* FILL IN HERE *) Admitted.

Example mult_2 : mult zero (plus three three) = zero.
Proof. (* FILL IN HERE *) Admitted.

Example mult_3 : mult two three = plus three three.
Proof. (* FILL IN HERE *) Admitted.

64: 2 stars, advanced (church_exp)

指数化:

(提示:多态性在这里起着至关重要的作用。但是,选择正确的类型进行迭代可能很棘手。如果遇到“宇宙不一致”错误,请尝试迭代其他类型。迭代cnat本身通常是有问题的。)

Definition exp (n m : cnat) : cnat
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.

Example exp_1 : exp two two = plus two two.
Proof. (* FILL IN HERE *) Admitted.

Example exp_2 : exp three zero = one.
Proof. (* FILL IN HERE *) Admitted.

Example exp_3 : exp three two = plus (mult two (mult two two)) one.
Proof. (* FILL IN HERE *) Admitted.
【学习】函数语言程序设计 文章被收录于专栏

函数语言程序设计 Coq章节 Ch1 Basics【COQ中的函数编程】 Ch2 Induction【归纳法证明】 Ch3 Lists【使用结构化数据】 Ch4 Poly【多态性与高阶函数】 Ch5 Tactics【更基本的战术】 Ch6 Logic【COQ中的逻辑】 Ch7 IndProp【归纳定义命题】 Ch8 Maps【全图和局部图】 Ch9 Rel【关系的性质】

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务