Definition update2 {A B : Type} (A_eq_dec : forall x y : A, {x = y} + {x <> y}) (f : A -> A -> B) (x y : A) (v : B) :=
  fun x' y' => if sumbool_and _ _ _ _ (A_eq_dec x x') (A_eq_dec y y') then v else f x' y'.Fixpoint collate {A B : Type} (A_eq_dec : forall x y : A, {x = y} + {x <> y}) (from : A) (f : A -> A -> list B) (ms : list (A * B)) :=
  match ms with
   | [] => f
   | (to, m) :: ms' => collate A_eq_dec from (update2 A_eq_dec f from to (f from to ++ [m])) ms'
  end.Fixpoint collate_ls {A B : Type} (A_eq_dec : forall x y : A, {x = y} + {x <> y}) (s : list A) (f : A -> A -> list B) (to : A) (m : B) :=
  match s with
   | [] => f
   | from :: s' => collate_ls A_eq_dec s' (update2 A_eq_dec f from to (f from to ++ [m])) to m
  end.Fixpoint filter_rel {A : Type} {rel : relation A} (A_rel_dec : forall x y : A, {rel x y} + {~ rel x y}) (x : A) (l : list A) :=
  match l with
   | [] => []
   | y :: tl => if A_rel_dec x y then y :: filter_rel A_rel_dec x tl else filter_rel A_rel_dec x tl
  end.Definition map2fst {A B : Type} (a : A) := map (fun (b : B) => (a, b)).Definition map2snd {A B : Type} (b : B) := map (fun (a : A) => (a, b)).

(* Specifications: *)
Lemma update2_diff1 : forall (sigma : A -> A -> B) x y v x' y', x <> x' -> update2 A_eq_dec sigma x y v x' y' = sigma x' y'.
Lemma update2_diff2 : forall (sigma : A -> A -> B) x y v x' y', y <> y' -> update2 A_eq_dec sigma x y v x' y' = sigma x' y'.
Lemma update2_diff_prod : forall (sigma : A -> A -> B) x y v x' y', (x, y) <> (x', y') -> update2 A_eq_dec sigma x y v x' y' = sigma x' y'.
Lemma update2_nop : forall (sigma : A -> A -> B) x y x' y', update2 A_eq_dec sigma x y (sigma x y) x' y' = sigma x' y'.
Lemma update2_eq : forall (sigma : A -> A -> B) x y x' y' v, x = x' -> y = y' -> update2 A_eq_dec sigma x y v x' y' = v.
Lemma update2_eq_prod : forall (sigma : A -> A -> B) x y x' y' v, (x, y) = (x', y') -> update2 A_eq_dec sigma x y v x' y' = v.
Lemma update2_same : forall (sigma : A -> A -> B) x y v, update2 A_eq_dec sigma x y v x y = v.
Lemma update2_nop_ext : forall (sigma : A -> A -> B) x y, update2 A_eq_dec sigma x y (sigma x y) = sigma.
Lemma update2_nop_ext' : forall (sigma : A -> A -> B) x y v, sigma x y = v -> update2 A_eq_dec sigma x y v = sigma.
Lemma update2_overwrite : forall (sigma : A -> A -> B) x y st st', update2 A_eq_dec (update2 A_eq_dec sigma x y st) x y st' = update2 A_eq_dec sigma x y st'.
Lemma update2_fun_comm : forall A B C A_eq_dec (f : B -> C) (st : A -> A -> B) x y v x' y', f (update2 A_eq_dec st x y v x' y') = update2 A_eq_dec (fun x y => f (st x y)) x y (f v) x' y'.