0

I have a function that doubles the elements of a list in the form

double [x1, x2, ...] = [x1, x1, x2, x2, ...]

namely

 fun double :: " 'a list ⇒ 'a list"
 where
   "double [] = []" |
   "double (x#xs) = x # x # double xs"

and a function that reverses the elements of a list with the help of another function snoc that adds an element to the right side of a list:

 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"

Now I want to prove that

 lemma rev_double: "rev (double xs) = double (rev xs)"

is true.

I tried to apply induction on xs

lemma rev_double: "rev (double xs) = double (rev xs)"
by (induction xs)

and I wrote an auxiliary lemma double_snoc that ensures that doubling a list is the same as doubling its first element and the rest of the list (which uses the function snocleft which inserts an element at the left end of a list)

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

I still haven't made any progress in proving the lemma. Do you have some solutions or hints on how to set up the prove?

chris
  • 4,988
  • 20
  • 36
Sophie Sepp
  • 521
  • 1
  • 5
  • 16
  • Just an aside: your `snocleft` is basically just list cons (i.e., `op #` in Isabelle/HOL) with the arguments swapped. Furthermore, since no recursion is going on, `fun` is somewhat overkill. You could use definition `definition "snocleft ys y = y # ys"` (which makes it obvious that your lemma could be statet `double (x # xs) = x # x # double xs` which directly follows from the definition of `double`). – chris Oct 20 '14 at 09:59

1 Answers1

0

You define your function as reverse, but in all of your lemmas, you use rev, referring to the pre-defined list reversal function rev.

What you mean is probably this:

lemma reverse_double: "reverse (double xs) = double (reverse xs)"

If you attempt to prove this by induction (with apply (induction xs)), you will get stuck in the induction case with the following goal:

snoc (snoc (double (reverse xs)) a) a =
   double (snoc (reverse xs) a)

This should be intuitively obvious: if you first snoc and then double, it is the same as first doubling and then snoc-ing twice. So let's prove this as an auxiliary lemma:

lemma double_snoc: "double (snoc xs x) = snoc (snoc (double xs) x) x"
  by (induction xs) auto

Now the proof of reverse_double goes through automatically:

lemma reverse_double: "reverse (double xs) = double (reverse xs)"
  by (induction xs) (auto simp: double_snoc)
Manuel Eberl
  • 7,858
  • 15
  • 24