Section Zip.
Variables (K : ordType) (V : Type) (zip_f : V -> V -> option V).
Variable (unit_f : V -> V).
Variable (comm : commutative zip_f).
Variable (assoc : forall x y z,
obind (zip_f x) (zip_f y z) = obind (zip_f^~ z) (zip_f x y)).
Variable (unitL : forall x, zip_f (unit_f x) x = Some x).
Variable (unitE : forall x y,
(exists z, zip_f x y = Some z) <-> unit_f x = unit_f y).
Fixpoint zip' (s1 s2 : seq (K * V)) :=
match s1, s2 with
[::], [::] => Some [::]
| (k1, v1)::s1', (k2, v2)::s2' =>
if k1 == k2 then
if zip_f v1 v2 is Some v then
if zip' s1' s2' is Some s' then Some ((k1, v) :: s')
else None
else None
else None
| _, _ => None
end.
Definition zip_unit' (s : seq (K * V)) := mapf' unit_f s.
Definition zip_unit f :=
let: FinMap s pf := f in FinMap (zip_unit_sorted' pf).
(* Now lemmas for interaction of zip with the other primitives *)
(* The other direction of the zip_fnd lemma *)

Lemma zunit_fcat f1 f2 :
zip_unit (fcat f1 f2) = fcat (zip_unit f1) (zip_unit f2).