我有一个函数,可以将表单元素加倍,格式为
double [x1, x2, ...] = [x1, x1, x2, x2, ...]
即
fun double :: " 'a list ⇒ 'a list"
where
"double [] = []" |
"double (x#xs) = x # x # double xs"
和一个函数,它在另一个函数snoc
的帮助下反转列表的元素,该函数在列表的右侧添加了一个元素:
fun snoc :: "'a list ⇒ 'a ⇒ 'a list"
where
"snoc [] x = [x]" |
"snoc (y # ys) x = y # (snoc ys x)"
fun reverse :: "'a list ⇒ 'a list"
where
"reverse [] = []" |
"reverse (x # xs) = snoc (reverse xs) x"
现在我要证明
lemma rev_double: "rev (double xs) = double (rev xs)"
是真的。
我尝试在xs
lemma rev_double: "rev (double xs) = double (rev xs)"
by (induction xs)
我编写了一个辅助引理double_snoc
,确保加倍列表与加倍其第一个元素和列表的其余部分(使用函数snocleft
相同,后者在列表的左端)
fun snocleft::"'a list ⇒ 'a ⇒ 'a list "
where
"snocleft [] x = [x]" |
"snocleft (y # ys) x = x # (y # ys)"
lemma double_snoc: "double (snocleft xs y) = y # y # double xs"
by (induction xs) auto
我在证明引理方面仍未取得任何进展。您对如何设置证明有一些解决方案或提示吗?
答案 0 :(得分:0)
您将函数定义为reverse
,但在所有引理中,您使用rev
,指的是预定义列表反转函数rev
。
你的意思可能就是这样:
lemma reverse_double: "reverse (double xs) = double (reverse xs)"
如果你试图通过归纳来证明这一点(使用apply (induction xs)
),你将陷入诱导案例,并达到以下目标:
snoc (snoc (double (reverse xs)) a) a =
double (snoc (reverse xs) a)
这应该是直观明显的:如果你第一次snoc然后加倍,它就像第一次加倍然后再狙击两次一样。因此,让我们证明这是一个辅助引理:
lemma double_snoc: "double (snoc xs x) = snoc (snoc (double xs) x) x"
by (induction xs) auto
现在reverse_double
的证明会自动完成:
lemma reverse_double: "reverse (double xs) = double (reverse xs)"
by (induction xs) (auto simp: double_snoc)