Section DEFINITIONS.
Variable R : Type.
Variable (rO rI : R) (radd rmul rsub: R->R->R) (ropp : R -> R).
Variable req : R -> R -> Prop.
Notation "0" := rO.  Notation "1" := rI.
Infix "==" := req. Infix "+" := radd. Infix "*" := rmul.
Infix "-" := rsub. Notation "- x" := (ropp x).
(** Semi Ring *)
Record semi_ring_theory : Prop := mk_srt {
SRadd_0_l   : forall n, 0 + n == n;
SRadd_comm  : forall n m, n + m == m + n ;
SRadd_assoc : forall n m p, n + (m + p) == (n + m) + p;
SRmul_1_l   : forall n, 1*n == n;
SRmul_0_l   : forall n, 0*n == 0;
SRmul_comm  : forall n m, n*m == m*n;
SRmul_assoc : forall n m p, n*(m*p) == (n*m)*p;
SRdistr_l   : forall n m p, (n + m)*p == n*p + m*p
}.
(** Almost Ring *)
(*Almost ring are no ring : Ropp_def is missing **)
Record almost_ring_theory : Prop := mk_art {
ARadd_0_l   : forall x, 0 + x == x;
ARadd_comm  : forall x y, x + y == y + x;
ARadd_assoc : forall x y z, x + (y + z) == (x + y) + z;
ARmul_1_l   : forall x, 1 * x == x;
ARmul_0_l   : forall x, 0 * x == 0;
ARmul_comm  : forall x y, x * y == y * x;
ARmul_assoc : forall x y z, x * (y * z) == (x * y) * z;
ARdistr_l   : forall x y z, (x + y) * z == (x * z) + (y * z);
ARopp_mul_l : forall x y, -(x * y) == -x * y;
ARopp_add   : forall x y, -(x + y) == -x + -y;
ARsub_def   : forall x y, x - y == x + -y
}.
(** Ring *)
Record ring_theory : Prop := mk_rt {
Radd_0_l    : forall x, 0 + x == x;
Radd_comm   : forall x y, x + y == y + x;
Radd_assoc  : forall x y z, x + (y + z) == (x + y) + z;
Rmul_1_l    : forall x, 1 * x == x;
Rmul_comm   : forall x y, x * y == y * x;
Rmul_assoc  : forall x y z, x * (y * z) == (x * y) * z;
Rdistr_l    : forall x y z, (x + y) * z == (x * z) + (y * z);
Rsub_def    : forall x y, x - y == x + -y;
Ropp_def    : forall x, x + (- x) == 0
}.
(** Equality is extensional *)
Record sring_eq_ext : Prop := mk_seqe {
(* SRing operators are compatible with equality *)
SRadd_ext : Proper (req ==> req ==> req) radd;
SRmul_ext : Proper (req ==> req ==> req) rmul
}.
Record ring_eq_ext : Prop := mk_reqe {
(* Ring operators are compatible with equality *)
Radd_ext : Proper (req ==> req ==> req) radd;
Rmul_ext : Proper (req ==> req ==> req) rmul;
Ropp_ext : Proper (req ==> req) ropp
}.
(** Interpretation morphisms definition*)
Section MORPHISM.
Variable C:Type.
Variable (cO cI : C) (cadd cmul csub : C->C->C) (copp : C->C).
Variable ceqb : C->C->bool.
(* [phi] est un morphisme de [C] dans [R] *)
Variable phi : C -> R.
Infix "+!" := cadd. Infix "-!" := csub.
Infix "*!" := cmul. Notation "-! x" := (copp x).
Infix "?=!" := ceqb. Notation "[ x ]" := (phi x).
(*for semi rings*)
Record semi_morph : Prop := mkRmorph {
Smorph0 : [cO] == 0;
Smorph1 : [cI] == 1;
Smorph_add : forall x y, [x +! y] == [x]+[y];
Smorph_mul : forall x y, [x *! y] == [x]*[y];
Smorph_eq  : forall x y, x?=!y = true -> [x] == [y]
}.
(* for rings*)
Record ring_morph : Prop := mkmorph {
morph0    : [cO] == 0;
morph1    : [cI] == 1;
morph_add : forall x y, [x +! y] == [x]+[y];
morph_sub : forall x y, [x -! y] == [x]-[y];
morph_mul : forall x y, [x *! y] == [x]*[y];
morph_opp : forall x, [-!x] == -[x];
morph_eq  : forall x y, x?=!y = true -> [x] == [y]
}.
Section SIGN.
Variable get_sign : C -> option C.
Record sign_theory : Prop := mksign_th {
sign_spec : forall c c', get_sign c = Some c' -> c ?=! -! c' = true
}.
End SIGN.
Definition get_sign_None (c:C) := @None C.

(* Specifications: *)
Lemma get_sign_None_th : sign_theory get_sign_None.
Section POWER.