Definition flatten := foldr cat (Nil T).Definition shape := map (@size T).Fixpoint reshape sh s :=
  if sh is n :: sh' then take n s :: reshape sh' (drop n s) else [::].Definition flatten_index sh r c := sumn (take r sh) + c.Definition reshape_offset sh i := i - sumn (take (reshape_index sh i) sh).

(* Specifications: *)
Lemma size_flatten ss : size (flatten ss) = sumn (shape ss).
Lemma flatten_cat ss1 ss2 : flatten (ss1 ++ ss2) = flatten ss1 ++ flatten ss2.
Lemma size_reshape sh s : size (reshape sh s) = size sh.
Lemma nth_reshape (sh : seq nat) l n : nth [::] (reshape sh l) n = take (nth 0 sh n) (drop (sumn (take n sh)) l).
Lemma flattenK ss : reshape (shape ss) (flatten ss) = ss.
Lemma reshapeKr sh s : size s <= sumn sh -> flatten (reshape sh s) = s.
Lemma reshapeKl sh s : size s >= sumn sh -> shape (reshape sh s) = sh.
Lemma flatten_rcons ss s : flatten (rcons ss s) = flatten ss ++ s.
Lemma rev_flatten ss : rev (flatten ss) = flatten (rev (map rev ss)).
Lemma nth_shape ss i : nth 0 (shape ss) i = size (nth [::] ss i).
Lemma shape_rev ss : shape (rev ss) = rev (shape ss).
Lemma eq_from_flatten_shape ss1 ss2 : flatten ss1 = flatten ss2 -> shape ss1 = shape ss2 -> ss1 = ss2.
Lemma rev_reshape sh s : size s = sumn sh -> rev (reshape sh s) = map rev (reshape (rev sh) (rev s)).
Lemma reshape_rcons s sh n (m := sumn sh) : m + n = size s -> reshape (rcons sh n) s = rcons (reshape sh (take m s)) (drop m s).
Lemma flatten_indexP sh r c : c < nth 0 sh r -> flatten_index sh r c < sumn sh.
Lemma reshape_indexP sh i : i < sumn sh -> reshape_index sh i < size sh.
Lemma reshape_offsetP sh i : i < sumn sh -> reshape_offset sh i < nth 0 sh (reshape_index sh i).
Lemma reshape_indexK sh i : flatten_index sh (reshape_index sh i) (reshape_offset sh i) = i.
Lemma flatten_indexKl sh r c : c < nth 0 sh r -> reshape_index sh (flatten_index sh r c) = r.
Lemma flatten_indexKr sh r c : c < nth 0 sh r -> reshape_offset sh (flatten_index sh r c) = c.
Lemma nth_flatten x0 ss i (r := reshape_index (shape ss) i) : nth x0 (flatten ss) i = nth x0 (nth [::] ss r) (reshape_offset (shape ss) i).
Lemma map_flatten S T (f : T -> S) ss : map f (flatten ss) = flatten (map (map f) ss).
Lemma sumn_flatten (ss : seq (seq nat)) : sumn (flatten ss) = sumn (map sumn ss).
Lemma map_reshape T S (f : T -> S) sh s : map (map f) (reshape sh s) = reshape sh (map f s).