SF习题答案(4)(LF-POLY)

Exercise 1: 2 stars, standard, optional (poly_exercises)

Here are a few simple exercises, just like ones in the Lists chapter, for practice with polymorphism. Complete the proofs below.
Theorem app_nil_r : ∀(X:Type), ∀l:list X,
l ++ [] = l.
Proof.
(* FILL IN HERE ) Admitted.
Theorem app_assoc : ∀A (l m n:list A),
l ++ m ++ n = (l ++ m) ++ n.
Proof.
(
FILL IN HERE ) Admitted.
Lemma app_length : ∀(X:Type) (l1 l2 : list X),
length (l1 ++ l2) = length l1 + length l2.
Proof.
(
FILL IN HERE *) Admitted.

解析:比较简单,对列表进行归纳证明,根据目标的不同应用不同的策略即可完成证明。

Theorem app_nil_r : forall (X:Type), forall l:list X,
  l ++ [] = l.
Proof.
  intros X l. induction l as [| n l'].
  - simpl. reflexivity.
  - simpl. rewrite IHl'. reflexivity. Qed.

Theorem app_assoc : forall A (l m n:list A),
  l ++ m ++ n = (l ++ m) ++ n.
Proof.
  intros A l m n. induction l as [| a l'].
  - simpl. reflexivity.
  - simpl. rewrite IHl'. reflexivity. Qed.

Lemma app_length : forall (X:Type) (l1 l2 : list X),
  length (l1 ++ l2) = length l1 + length l2.
Proof.
  intros x l1 l2. induction l1 as [| n l1'].
  - simpl. reflexivity.
  - simpl. rewrite IHl1'. reflexivity. Qed.

Exercise 2: 2 stars, standard, optional (more_poly_exercises)

Here are some slightly more interesting ones…
Theorem rev_app_distr: ∀X (l1 l2 : list X),
rev (l1 ++ l2) = rev l2 ++ rev l1.
Proof.
(* FILL IN HERE ) Admitted.
Theorem rev_involutive : ∀X : Type, ∀l : list X,
rev (rev l) = l.
Proof.
(
FILL IN HERE *) Admitted.

解析:对于第一个定理,对列表l1进行归纳后需要使用到之前证明号的策略app_nil_r和app_assoc,使用重写即可,剩下的根据目标选择定理完成证明;对于第二个定理,归纳后证明过程中遇到了rev (l ++ [n]),要将其变换为n :: rev (l)的形式,因此加入了辅助定理rev_nat_r:rev (l ++ [n]) = n :: rev (l)并进行了证明,在证明中应用这个定理完成了证明。

Theorem rev_app_distr: forall X (l1 l2 : list X),
  rev (l1 ++ l2) = rev l2 ++ rev l1.
Proof.
  intros X l1 l2. induction l1 as [| n l1'].
  - simpl. rewrite app_nil_r. reflexivity.
  - simpl. rewrite IHl1'. rewrite app_assoc. reflexivity. Qed.

Lemma rev_nat_r : forall X : Type, forall n : X, forall l : list X,
  rev (l ++ [n]) = n :: rev (l).
Proof.
  intros X n l. induction l as [| a l'].
  - simpl. reflexivity.
  - simpl. rewrite -> IHl'. reflexivity. Qed.

Theorem rev_involutive : forall X : Type, forall l : list X,
  rev (rev l) = l.
Proof.
  intros X l. induction l as [| n l'].
  - simpl. reflexivity.
  - simpl. rewrite -> rev_nat_r. rewrite -> IHl'. reflexivity. Qed.

Exercise 3: 2 stars, standard, recommended (split)

The function split is the right inverse of combine: it takes a list of pairs and returns a pair of lists. In many functional languages, it is called unzip.
Fill in the definition of split below. Make sure it passes the given unit test.
Fixpoint split {X Y : Type} (l : list (XY))
: (list X) * (list Y)
(
REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_split:
split [(1,false);(2,false)] = ([1;2],[false;false]).
Proof.
(
FILL IN HERE *) Admitted.

解析:通过题目要求完成split的递归定义,使得例子可以运行通过。递归定义前需要先定义一个cons_pair的操作,从而让递归函数split只专注于自身的递归。

Definition cons_pair {X Y : Type} (p: X * Y) (l : (list X * list Y)) : prod (list X) (list Y) :=
  match p with
  | (x1,y1) => match l with
               | (lx,ly) => (cons x1 lx, cons y1 ly)
               end
  end.

Fixpoint split {X Y : Type} (l : list (X*Y))
               : (list X) * (list Y) :=
  match l with
  | nil  => ([], [])
  | (x, y) :: l' => cons_pair (x, y) (split l')
  end.

Example test_split:
  split [(1,false);(2,false)] = ([1;2],[false;false]).
Proof. reflexivity. Qed.

Exercise 4: 1 star, standard, optional (hd_error_poly)

Complete the definition of a polymorphic version of the hd_error function from the last chapter. Be sure that it passes the unit tests below.
Definition hd_error {X : Type} (l : list X) : option X
(* REPLACE THIS LINE WITH “:= your_definition .” *). Admitted.

解析:比较简单,根据函数的意义,对参数l进行match分条件定义即可完成该函数的定义。

Definition hd_error {X : Type} (l : list X) : option X :=
  match l with
  | [] => None
  | a :: l' => Some a
  end.

Exercise 5: 2 stars, standard (filter_even_gt7)

Use filter (instead of Fixpoint) to write a Coq function filter_even_gt7 that takes a list of natural numbers as input and returns a list of just those that are even and greater than 7.
Definition filter_even_gt7 (l : list nat) : list nat
(* REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_filter_even_gt7_1 :
filter_even_gt7 [1;2;6;9;10;3;12;8] = [10;12;8].
(
FILL IN HERE ) Admitted.
Example test_filter_even_gt7_2 :
filter_even_gt7 [5;2;6;19;129] = [].
(
FILL IN HERE *) Admitted.

解析:函数filter_even_gt7的目的是过滤大于7的偶数,通过在例子中定义的filter函数,以及我们定义一个判断某个数是不是大于7偶数的函数even_gt7,即可完成函数的定义。

Fixpoint even_gt7  (n : nat) : bool :=
  match 7 <=? n with
  | true => if (evenb n) then true else false
  | false => false
  end.

Definition filter_even_gt7 (l : list nat) : list nat:=
  filter even_gt7 l.

Example test_filter_even_gt7_1 :
  filter_even_gt7 [1;2;6;9;10;3;12;8] = [10;12;8].
Proof. reflexivity.  Qed.

Example test_filter_even_gt7_2 :
  filter_even_gt7 [5;2;6;19;129] = [].
Proof. reflexivity.  Qed.

Exercise 6: 3 stars, standard (partition)

Use filter to write a Coq function partition:
partition : ∀X : Type,
(X → bool) → list X → list X * list X
Given a set X, a test function of type X → bool and a list X, partition should return a pair of lists. The first member of the pair is the sublist of the original list containing the elements that satisfy the test, and the second is the sublist containing those that fail the test. The order of elements in the two sublists should be the same as their order in the original list.
Definition partition {X : Type}
(test : X → bool)
(l : list X)
: list X * list X
(* REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_partition1: partition oddb [1;2;3;4;5] = ([1;3;5], [2;4]).
(
FILL IN HERE ) Admitted.
Example test_partition2: partition (fun x ⇒ false) [5;9;0] = ([], [5;9;0]).
(
FILL IN HERE *) Admitted.

解析:题目要求将一个列表变为两个列表,一个满足过滤条件,一个不满足。参考之前filter函数的定义,完成一个过滤条件不满足的定义filter_not。然后在定义函数partition,将两部分使用pair函数结合起来就可完成定义。

Fixpoint filter_not {X:Type} (test: X->bool) (l:list X)
                : (list X) :=
  match l with
  | []     => []
  | h :: t => if test h then filter_not test t
                        else h :: (filter_not test t)
  end.

Definition partition {X : Type}
                     (test : X -> bool)
                     (l : list X)
                   : list X * list X :=
  pair (filter test l) (filter_not test l).

Example test_partition1: partition oddb [1;2;3;4;5] = ([1;3;5], [2;4]).
Proof. reflexivity. Qed.
Example test_partition2: partition (fun x => false) [5;9;0] = ([], [5;9;0]).
Proof. reflexivity. Qed.

Exercise 7: 3 stars, standard (map_rev)

Show that map and rev commute. You may need to define an auxiliary lemma.
Theorem map_rev : ∀(X Y : Type) (f : X → Y) (l : list X),
map f (rev l) = rev (map f l).
Proof.
(* FILL IN HERE *) Admitted.

解析:证明过程中,对列表l归纳后,出现了map f l ++ [f n],我们需要其变换为map f (l ++ [n]),所以定义了函数map_l_n:map f l ++ [f n] = map f (l ++ [n])并进行了证明。应用rewrite map_l_n即完成了定理的证明。

Lemma map_l_n : forall (X Y: Type) (f : X -> Y) (l : list X) (n : X),
  map f l ++ [f n] = map f (l ++ [n]).
Proof.
  intros X Y f l n. induction l as [| s l'].
  - simpl. reflexivity.
  - simpl. rewrite IHl'. reflexivity. Qed.

Theorem map_rev : forall (X Y : Type) (f : X -> Y) (l : list X),
  map f (rev l) = rev (map f l).
Proof.
  intros X Y f l. induction l as [| n l'].
  - simpl. reflexivity.
  - simpl. rewrite <- IHl'. rewrite map_l_n. reflexivity. Qed.

Exercise 8:2 stars, standard, recommended (flat_map)

The function map maps a list X to a list Y using a function of type X → Y. We can define a similar function, flat_map, which maps a list X to a list Y using a function f of type X → list Y. Your definition should work by ‘flattening’ the results of f, like so:
flat_map (fun n ⇒ [n;n+1;n+2]) [1;5;10]
= [1; 2; 3; 5; 6; 7; 10; 11; 12].
Fixpoint flat_map {X Y: Type} (f: X → list Y) (l: list X)
: (list Y)
(* REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_flat_map1:
flat_map (fun n ⇒ [n;n;n]) [1;5;4]
= [1; 1; 1; 5; 5; 5; 4; 4; 4].
(
FILL IN HERE *) Admitted.

解析:对列表进行某个操作后再合并为一个新的列表,参考之前filter的定义,可以递归完成函数flat_map的定义。

Fixpoint flat_map {X Y: Type} (f: X -> list Y) (l: list X)
                   : (list Y) :=
  match l with
  | []     => []
  | h :: t => (f h) ++ (flat_map f t)
  end.

Example test_flat_map1:
  flat_map (fun n => [n;n;n]) [1;5;4]
  = [1; 1; 1; 5; 5; 5; 4; 4; 4].
Proof. reflexivity. Qed.

Exercise 9:2 stars, standard (fold_length)

Many common functions on lists can be implemented in terms of fold. For example, here is an alternative definition of length:
Definition fold_length {X : Type} (l : list X) : nat :=
fold (fun _ n ⇒ S n) l 0.
Prove the correctness of fold_length. (Hint: It may help to know that reflexivity simplifies expressions a bit more aggressively than simpl does — i.e., you may find yourself in a situation where simpl does nothing but reflexivity solves the goal.)
Theorem fold_length_correct : ∀X (l : list X),
fold_length l = length l.
Proof.
(* FILL IN HERE *) Admitted.

解析:证明题目中定理的函数fold_length和例子中定义的函数length的等价性。对列表l进行归纳,然后使用重写策略进行证明即可。

Theorem fold_length_correct : forall X (l : list X),
  fold_length l = length l.
Proof.
  intros X l. induction l as [| n l'].
  - reflexivity.
  - simpl. rewrite <- IHl'. reflexivity.
Qed.

Exercise 10: 3 stars, standard (fold_map)

We can also define map in terms of fold. Finish fold_map below.
Definition fold_map {X Y: Type} (f: X → Y) (l: list X) : list Y
(* REPLACE THIS LINE WITH “:= your_definition .” *). Admitted.

解析:定义一个函数,对列表的每一个元素执行操作,最后再形成一个新的列表,主要的对元素操作之后还需要和现有列表连接起来。其定义和测试如下:

Definition fold_map {X Y: Type} (f: X -> Y) (l: list X) : list Y :=
  fold (fun x lx => [f x] ++ lx) l [].

Example test_fold_map1: fold_map (fun x => plus 3 x) [2;0;2] = [5;3;5].
Proof. reflexivity. Qed.

Exercise 11: 2 stars, advanced (currying)

Definition prod_curry {X Y Z : Type}
(f : X * Y → Z) (x : X) (y : Y) : Z := f (x, y).
Definition prod_uncurry {X Y Z : Type}
(f : X → Y → Z) (p : X * Y) : Z
(* REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Thought exercise: before running the following commands, can you calculate the types of prod_curry and prod_uncurry?
Theorem uncurry_curry : ∀(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 : ∀(X Y Z : Type)
(f : (X * Y) → Z) (p : X * Y),
prod_uncurry (prod_curry f) p = f p.
Proof.
(
FILL IN HERE *) Admitted.

解析:根据题目中定义的函数curry_uncurry和prod_uncurry,证明其一些转换关系式正确的,通过函数的展开unfold和归纳展开destruct,即可完成证明。

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.
  intros. reflexivity. Qed.

Theorem curry_uncurry : forall (X Y Z : Type)
                        (f : (X * Y) -> Z) (p : X * Y),
  prod_uncurry (prod_curry f) p = f p.
Proof.
  intros. unfold prod_curry, prod_uncurry. destruct p. reflexivity. Qed.

本章后面的习题是有关church数的函数定义与定理证明,内容较多,且需要一些课外知识,将独立一篇进行分析与介绍,而不仅仅是完成书中的题目。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值