Zulip Chat Archive

Stream: new members

Topic: reverse_reverse definition


Ada Weird (Aug 19 2025 at 17:46):

I've reached ch 8 of TPIL after a short break while I dealt with other stuff, and for exercise 2 they're asking me to define reverse and prove reverse (reverse xs) = xs). I've gotten the proof to the following point

def reverse: List α  List α
| [] => []
| x :: xs =>  xs ++ [x]

theorem reverse_reverse:  l : List α, reverse (reverse l) = l := by
  intro l
  cases l
  case nil =>
    rfl
  case cons head tail =>
    unfold reverse
    simp
    sorry

But I'm not sure how to continue. It seems intuitive to me that I can ignore the [] case in the goal because it's being matched on tail ++ [head] which is definitionally not [], and that I can sub head and tail in for x and xs but I'm not sure how to tell that to lean.

Ada Weird (Aug 19 2025 at 17:46):

Oh and the current goal state

(match tail ++ [head] with
  | [] => []
  | x :: xs => xs ++ [x]) =
  head :: tail

Ada Weird (Aug 19 2025 at 17:48):

Oh wait no you can't sub in head for x. duh

Ada Weird (Aug 19 2025 at 17:49):

simp would have just done that for me if it could. I need to eliminate the [] case and then I dunno what

Aaron Liu (Aug 19 2025 at 17:57):

You might want to try proving reverse_append first

Ada Weird (Aug 19 2025 at 17:58):

Alright. I don't recognize that name. What's the theorem?

Aaron Liu (Aug 19 2025 at 17:59):

reverse (a ++ b) = reverse b ++ reverse a

Ada Weird (Aug 19 2025 at 17:59):

Thank you!

Ada Weird (Aug 19 2025 at 18:11):

Wait. I modified the definition of reverse to just use ++ instead of List.concat and I forgot to reverse xs. Yeah that'd make things harder.

Ruben Van de Velde (Aug 19 2025 at 18:28):

It can be difficult to prove things that are false

Ada Weird (Aug 19 2025 at 18:29):

Generally speaking yes

Ada Weird (Aug 19 2025 at 18:51):

Okay here is where we are

def reverse: List α  List α
| [] => []
| x :: xs =>  (reverse xs) ++ [x]

theorem reverse_reverse:  l : List α, reverse (reverse l) = l := by
  intro l
  induction l
  case nil =>
    rfl
  case cons head tail hl =>
    unfold reverse
    conv in reverse (head :: tail) => {
      unfold reverse
    }
    sorry

With goal state before the sorry being

1 goal
α : Type u_1
head : α
tail : List α
hl : reverse (reverse tail) = tail
 (match reverse tail ++ [head] with
  | [] => []
  | x :: xs => reverse xs ++ [x]) =
  head :: tail

Ada Weird (Aug 19 2025 at 18:51):

Again, I know that the [] case is irrelevant but I dunno how to eliminate it

Ada Weird (Aug 19 2025 at 18:51):

I dunno if that'd actually make things easier

Ada Weird (Aug 19 2025 at 18:52):

Or am I just barking up the wrong tree?

Aaron Liu (Aug 19 2025 at 18:53):

Did you prove reverse_append first?

Ada Weird (Aug 19 2025 at 18:53):

Yes

Ada Weird (Aug 19 2025 at 18:54):

theorem reverse_append:  a b : List α, reverse (a ++ b) = reverse b ++ reverse a := by
  intro a b
  induction a
  case nil =>
    simp
    rfl
  case cons head_a tail_a ha=>
    simp
    conv =>
      lhs
      unfold reverse
      rw [ha]
    conv =>
      rhs;rhs
      unfold reverse
    simp

Aaron Liu (Aug 19 2025 at 18:55):

So reverse (reverse tail ++ [head]) = reverse [head] ++ reverse (reverse tail) = [head] ++ tail = head :: tail

Ada Weird (Aug 19 2025 at 18:56):

Alright lemme parse that out real quick

Ada Weird (Aug 19 2025 at 18:57):

Oh I see. Yeah I've been going about this wrong

Ada Weird (Aug 19 2025 at 19:03):

def reverse: List α  List α
| [] => []
| x :: xs =>  (reverse xs) ++ [x]

theorem reverse_len_1_list_eq_id:  x : α, reverse [x] = [x] :=by
  intro x
  rfl

theorem reverse_append:  a b : List α, reverse (a ++ b) = reverse b ++ reverse a := by
  intro a b
  induction a
  case nil =>
    simp
    rfl
  case cons head_a tail_a ha=>
    simp
    conv =>
      lhs
      unfold reverse
      rw [ha]
    conv =>
      rhs;rhs
      unfold reverse
    simp
theorem box_list (a: α) (b: List α): a :: b = [a] ++ b := by
  simp

theorem reverse_reverse:  l : List α, reverse (reverse l) = l := by
  intro l
  induction l
  case nil =>
    rfl
  case cons head tail hl =>
    rw [box_list, reverse_append, reverse_len_1_list_eq_id,
      reverse_append, reverse_len_1_list_eq_id, hl]

Ada Weird (Aug 19 2025 at 19:03):

Got it!

Ada Weird (Aug 19 2025 at 19:06):

I assume box_list is a builtin but I didn't feel like finding it and defining it is trivial

Robin Arnez (Aug 19 2025 at 19:30):

List.singleton_append?

Ada Weird (Aug 19 2025 at 19:32):

I can't just sub that in the rw like I can with box_list

Ada Weird (Aug 19 2025 at 19:33):

But I'll look at it

Ada Weird (Aug 19 2025 at 19:34):

Oh I need to reverse it. Duh


Last updated: Dec 20 2025 at 21:32 UTC