(* * Copyright (c) 2009-2010, Andrew Appel, Robert Dockins and Aquinas Hobor. * *)
Local Open Scope nat_scope.
Definition map_pair {A B C D} (f:A -> B) (g:C -> D) (x:A * C) : B * D :=
(f (fst x), g (snd x)).
Module Type ISOMORPHIC_KNOTS.
Declare Module TF : TY_FUNCTOR.
Declare Module K1 : KNOT with Module TF := TF.
Declare Module K2 : KNOT with Module TF := TF.
Parameter f : K1.knot -> K2.knot.
Parameter g : K2.knot -> K1.knot.
Definition fF : F K1.predicate -> F K2.predicate :=
fmap F (fun p : K1.knot * other -> K1.TF.T => p oo map_pair g (@id other)).
Definition gF : F K2.predicate -> F K1.predicate :=
fmap F (fun p : K2.knot * other -> K2.TF.T => p oo map_pair f (@id other)).

(* Specifications: *)
Axiom iso1 : f oo g = id K2.knot.
Axiom iso2 : g oo f = id K1.knot.
Axiom f_squash : forall n F1,
f (K1.squash (n, F1)) = K2.squash (n, fF F1).
Axiom g_squash : forall n F2,
g (K2.squash (n, F2)) = K1.squash (n, gF F2).
Axiom f_unsquash : forall k1 U1,
U1 = K1.unsquash k1 ->
K2.unsquash (f k1) = (fst U1, fF (snd U1)).
Axiom g_unsquash : forall k2 U2,
U2 = K2.unsquash k2 ->
K1.unsquash (g k2) = (fst U2, gF (snd U2)).