(* (efficient) reversal *)

Fixpoint catrev s1 s2 := if s1 is x :: s1' then catrev s1' (x :: s2) else s2.(* rev must be defined outside a Section because Coq's end of section *)
(* "cooking" removes the nosimpl guard.                               *)

Definition rev T (s : seq T) := nosimpl (catrev s [::]).Notation count_mem x := (count (pred_of_simpl (pred1 x))).Notation "'all_ view" := (allPP _ (fun _ => view))
  (at level 4, right associativity, format "''all_' view").

(* Specifications: *)
Lemma seq2_ind T1 T2 (P : seq T1 -> seq T2 -> Type) : P [::] [::] -> (forall x1 x2 s1 s2, P s1 s2 -> P (x1 :: s1) (x2 :: s2)) -> forall s1 s2, size s1 = size s2 -> P s1 s2.
Lemma catrev_catl s t u : catrev (s ++ t) u = catrev t (catrev s u).
Lemma catrev_catr s t u : catrev s (t ++ u) = catrev s t ++ u.
Lemma catrevE s t : catrev s t = rev s ++ t.
Lemma rev_cons x s : rev (x :: s) = rcons (rev s) x.
Lemma size_rev s : size (rev s) = size s.
Lemma rev_cat s t : rev (s ++ t) = rev t ++ rev s.
Lemma rev_rcons s x : rev (rcons s x) = x :: rev s.
Lemma revK : involutive (@rev T).
Lemma filter_rev a s : filter a (rev s) = rev (filter a s).
Lemma count_rev a s : count a (rev s) = count a s.
Lemma has_rev a s : has a (rev s) = has a s.
Lemma all_rev a s : all a (rev s) = all a s.
Lemma take_rev s n : take n (rev s) = rev (drop (size s - n) s).
Lemma drop_rev s n : drop n (rev s) = rev (take (size s - n) s).