Definition bind {A B} (aopt: option A) (f: A -> option B): option B :=
match aopt with None => None | Some a => f a end.
Section CombineList.
Variable A: Type.
Variable f: A -> A -> A.
Fixpoint combinelist xs ys :=
match xs, ys with
nil, nil => Some nil
| (u::us),(v::vs) => bind (combinelist us vs) (fun l => Some (f u v :: l))
| _, _ => None
end.

(* Specifications: *)
Lemma combinelist_Zlength: forall xs ys zs,
combinelist xs ys = Some zs -> Zlength zs = Zlength xs /\ Zlength ys = Zlength xs.
Lemma combinelist_Some: forall xs ys, length xs = length ys ->
exists l, combinelist xs ys = Some l.
Lemma combinelist_SomeInv: forall xs ys l, combinelist xs ys = Some l ->
Zlength xs = Zlength ys.
Lemma combinelist_length:
forall xs ys l, Some l = combinelist xs ys -> length l = length ys.
Lemma combinelist_symm (C: forall a b, f a b = f b a):
forall xs ys, combinelist xs ys = combinelist ys xs.
Lemma combinelist_char_nth: forall xs ys l, combinelist xs ys = Some l ->
forall i d, (0 <= i < length l)%nat -> nth i l d = f (nth i xs d) (nth i ys d).
Lemma combinelist_char_Znth {d: Inhabitant A} xs ys l (C: combinelist xs ys = Some l)
i (L:0 <= i < Zlength l): Znth i l = f (Znth i xs) (Znth i ys).