intros.
unfold list_map'.
now rewrite map_rec_spec.
Qed.
(* The shape of a tree can be expressed by mapping (fun _ => tt) over it. *)
Fixpoint map {A B} (f : A -> B) (t : tree A) : tree B :=
match t with
| atom a => atom (f a)
| node l => node (List.map (map f) l)
end.
Definition shape {A} (t : tree A) : tree unit :=
map (fun _ => tt) t.
Fixpoint tree_map' {A B} (f : A -> B) (t : tree A) : tree B :=
let fix tree_map_loop {A B} (f : A -> B) (l : list (tree A)) acc :=
match l with
| [] => rev_rec acc []
| a :: l => tree_map_loop f l (map f a :: acc)
end in
match t with
| atom a => atom (f a)
| node l => node (tree_map_loop f l [])
end.
Definition tree_map_loop :=
fix tree_map_loop {A B} (f : A -> B) (l : list (tree A)) acc :=
match l with
| [] => rev_rec acc []
| a :: l => tree_map_loop f l (map f a :: acc)
end.

(* Specifications: *)
Lemma tree_map_loop_spec :
forall {A B} (f : A -> B) l acc,
tree_map_loop f l acc = rev acc ++ List.map (map f) l.
Theorem tree_map'_spec : forall {A B} (f : A -> B) (t : tree A),
tree_map' f t = map f t.