software foundations LF Lists

更多内容见 https://github.com/january147/software_foundations_notes

原始章节参考 software foundations LF Lists

pair和多元素匹配

(a, b)作为一个pair表示一个变量,在match的匹配列表左端,多个由逗号分隔但没有在括号里的变量表示匹配多个变量

(* Can't match on a pair with multiple patterns: *)
Definition bad_fst (p : natprod) : nat :=
(* match仅匹配一个变量p *)
match p with
(* 匹配规则定义了两个变量x和y,因此无法正常运行 *)
| x, y ⇒ x
end.

包含在一个括号内的多个使用逗号分隔的变量表示匹配一个变量,括号内的各个变量表示匹配整体变量内部的各个子变量模式

(* Can't match on multiple values with pair patterns: *)
Definition bad_minus (n m : nat) : nat :=
(* match要求匹配两个变量n和m *)
match n, m with
(* 匹配规则仅定义了一个变量,因此无法正常运行 *)
| (O , _ ) ⇒ O
| (S _ , O ) ⇒ n
| (S n', S m') ⇒ bad_minus n' m'
end.

Search

使用Search命令可以搜索之前已经定义和证明的定理。例如如下命令可以搜索Basics模块中所有使用了plus的定理

Search plus inside Basics.

使用如下命令可以搜索到包含(_ + _ = _ + _)模式的定理

Search (_ + _ = _ + _)

option

如果我们需要编写一个返回列表中第n个元素的函数,当n大于列表长度时需要一个能够表示错误的返回结果,可以定义如下类型作为返回结果。在有合法结果时返回合法结果,没有合法结果则返回一个特殊的表示错误的值。

Inductive natoption : Type :=
  | Some (n : nat)
  | None.

如下是使用上述类型作为返回结果的获取列表中第n个元素的函数。

Fixpoint nth_error' (l:natlist) (n:nat) : natoption :=
  match l with
  | nil => None
  | a :: l' => if n =? O then Some a
               else nth_error' l' (pred n)
  end.

该函数中没有使用match而使用了if语句。if可以视为一种针对特定类型的match, 由于coq没有定义内置的bool类型,因此if接受任何仅使用两个construct定义的类型的值,例如如下所示的T类型

Inductive T : Type :=
	| A 
	| B

其中由第一个construct(例如A)定义的值被匹配到then对应的表达式(即表示true), 由第二个constructor定义的值(例如B)被匹配到else对应的表达式(即表示false)。

重要练习

交替组合两个List

coq的Fixpoint要求必须在一个参数上递减,因此直接使用match l1, l2匹配两个参数进行递归定义是无法通过。(即下面的定义无法通过),因为对两个参数同时进行递归定义会导致coq无法判定递归的终止性。

Fixpoint alternate (l1 l2 : natlist) : natlist :=
  match l1,l2 with
  | nil, nil => nil
  | nil, h :: t => h :: (alternate nil t)
  | h :: t, nil => h :: (alternate t nil)
  | h1 :: t1, h2 :: t2 => h1 :: h2 :: (alternate t1 t2)
  end.

需要使用嵌套match首先在第一个参数上进行递减的递归定义,使coq能够确定该定义的终止性,然后再使用match处理第二个参数。

Fixpoint alternate (l1 l2 : natlist) : natlist :=
  match l1 with
  | nil => l2
  | h1 :: t1 => match l2 with
                | nil => l1
                | h2 :: t2 => h1 :: h2 :: (alternate t1 t2)
                end
  end.

列表逆序函数的单射性质

要证明的目标为rev l1 = rev l2 -> l1 = l2,可以看到该目标中假设部分rev l1 = rev l2包含了rev函数运算而目标部分没有运算,而我们目前学的tactics都是针对目标进行变换和操作,因此这个假设难以被用于证明目标。为了证明目标,我们需要对目标进行变化,使其包含rev函数,因而能够使用假设。根据rev_involutive定理forall l : natlist, rev (rev l) = l,我们可以将目标中的l1或者l2转换为rev (rev l1)或者rev (rev l2), 因此将rev函数引入了目标,就能够使用定理中的假设条件进行变换和证明了。

Theorem rev_injective : forall (l1 l2 : natlist),
    rev l1 = rev l2 -> l1 = l2.
Proof.
  intros l1 l2 H.
  rewrite <- rev_involutive.
  rewrite <- H.
  rewrite -> rev_involutive.
  reflexivity.
Qed.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值