swh:1:snp:1160b607213f14ec0f922dad3284705c8e588b30
Tip revision: 6561b69dcc30a72b8a78c97019cfc46e4df655f0 authored by Pierre-Yves Strub on 19 November 2021, 22:43:31 UTC
prune virtual tc
prune virtual tc
Tip revision: 6561b69
typeclass.ec
(* =====================================================================*)
require import AllCore List.
(* ==================================================================== *)
(* Typeclass examples *)
(* -------------------------------------------------------------------- *)
(* Set theory *)
type class finite = {
op enum : finite list
axiom enumP : forall (x : finite), x \in enum
}.
type class countable = {
op count : int -> countable
axiom countP : forall (x : countable), exists (n : int), x = count n
}.
(* -------------------------------------------------------------------- *)
(* Simple algebraic structures *)
type class magma = {
op mmul : magma -> magma -> magma
}.
(* TODO: when removing the type argument of associative, no explicit error message.
Should work anyway and if not, have a readable error message.*)
type class semigroup <: magma = {
axiom mmulA : associative<:semigroup> mmul
}.
(* TODO: why do I need this instead of using left_id and right_id directly?
Or even specifying the type?
Or even specifying semigroup and not magma? *)
pred left_id_mmul ['a <: semigroup] (e : 'a) = left_id e mmul.
pred right_id_mmul ['a <: semigroup] (e : 'a) = right_id e mmul.
type class monoid <: semigroup = {
op mid : monoid
axiom mmulr0 : left_id_mmul mid
axiom mmul0r : right_id_mmul mid
}.
(* TODO: same. *)
pred left_inverse_mid_mmul ['a <: monoid] (inv : 'a -> 'a) = left_inverse mid inv mmul.
type class group <: monoid = {
op minv : group -> group
axiom mmulN : left_inverse_mid_mmul minv
}.
type class ['a <: group] action = {
op amul : 'a -> action -> action
axiom identity :
forall (x : action), amul mid x = x
axiom compatibility :
forall (g h : 'a) (x : action), amul (mmul g h) x = amul g (amul h x)
}.
(* TODO: make one of these work, and then finish the hierarchy here:
https://en.wikipedia.org/wiki/Magma_(algebra) *)
type fingroup <: group & finite.
(* TODO: we may want to rename mmul to ( + ) and build this from group *)
type class comgroup = {
op gzero : comgroup
op gopp : comgroup -> comgroup
op gadd : comgroup -> comgroup -> comgroup
axiom addr0 : left_id gzero gadd
axiom addrN : left_inverse gzero gopp gadd
axiom addrC : commutative gadd
axiom addrA : associative gadd
}.
(* -------------------------------------------------------------------- *)
(* Advanced algebraic structures *)
(*TODO: we don't have here the issues we had with semigroup and monoid,
probably because left_distributive was adequatly typed by ( * )
before beign applied to ( + ). *)
type class comring <: comgroup = {
op one : comring
op ( * ) : comring -> comring -> comring
axiom mulr1 : left_id one ( * )
axiom mulrC : commutative ( * )
axiom mulrA : associative ( * )
axiom mulrDl : left_distributive ( * ) gadd
}.
type class ['a <: comring] commodule <: comgroup = {
op ( ** ) : 'a -> commodule -> commodule
axiom scalerDl : forall (a b : 'a) (x : commodule),
(gadd a b) ** x = gadd (a ** x) (b ** x)
axiom scalerDr : forall (a : 'a) (x y : commodule),
a ** (gadd x y) = gadd (a ** x) (a ** y)
}.
(* ==================================================================== *)
(* Operator examples *)
(* -------------------------------------------------------------------- *)
(* Set theory *)
op all_finite ['a <: finite] (p : 'a -> bool) =
all p enum<:'a>.
op all_countable ['a <: countable] (p : 'a -> bool) =
forall (n : int), p (count<:'a> n).
(* ==================================================================== *)
(* Lemma examples *)
(* -------------------------------------------------------------------- *)
(* Set theory *)
(* TODO: why is the rewrite/all_finite needed? *)
lemma all_finiteP ['a <: finite] p : (all_finite p) <=> (forall (x : 'a), p x).
proof. by rewrite/all_finite allP; split => Hp x; rewrite Hp // enumP. qed.
lemma all_countableP ['a <: countable] p : (all_countable p) <=> (forall (x : 'a), p x).
proof.
rewrite/all_countable; split => [Hp x|Hp n].
by case (countP x) => n ->>; rewrite Hp.
by rewrite Hp.
qed.
lemma all_finite_countable ['a <: finite & countable] (p : 'a -> bool) : (all_finite p) <=> (all_countable p).
proof. by rewrite all_finiteP all_countableP. qed.
(* ==================================================================== *)
(* Instance examples *)
(* -------------------------------------------------------------------- *)
(* Set theory *)
op bool_enum = [true; false].
(* TODO: we want to be ale to give the list directly.*)
instance finite with bool
op enum = bool_enum.
realize enumP.
proof. by case. qed.
(* -------------------------------------------------------------------- *)
(* Simple algebraic structures *)
op izero = 0.
instance comgroup with int
op gzero = izero
op gadd = CoreInt.add
op gopp = CoreInt.opp.
realize addr0.
apply: addr0.
have : left_id izero Int.(+).
locate left_id.
rewrite /left_id.
rewrite /izero.
move=> x /=.
rewrite /izero.
by trivial.
realize addrN by trivial.
(* TODO: what? *)
(*
realize addrC by apply addrC.
realize addrC by apply Ring.IntID.addrC.
*)
realize addrC by admit.
realize addrA by admit.
(* -------------------------------------------------------------------- *)
(* Advanced algebraic structures *)
op ione = 1.
(* TODO: this automatically fetches the only instance of comgroup we have defined for int.
We should give the choice of which instance to use, by adding as desired_name after the with.
Also we should give the choice to define directly an instance of comring with int. *)
instance comring with int
op one = ione
op ( * ) = CoreInt.mul.
realize mulr1 by trivial.
realize mulrC by rewrite mulrC.
realize mulrA by rewrite mulrA.
realize mulrDl.
proof.
print mulrDl.
move => x y z.
move: (Ring.IntID.mulrDl x y z).
move => HmulrDl.
(* TODO: what? *)
admit.
qed.
type 'a poly = 'a list.
op pzero ['a] : 'a poly = [].
op padd ['a <: comgroup] p q =
mkseq (fun n => (nth zero<:'a> p n) + (nth zero<:'a> q n)) (max (size p) (size q)).
op pinv ['a <: comgroup] = map [-]<:'a>.
op pone ['a <: comring] = [one <:'a>].
op pmul ['a <: comring] : 'a poly -> 'a poly -> 'a poly.
op ipmul ['a <: comring] (x : 'a) = map (( * ) x).
(* TODO: we may not need to specify the <:'a>. *)
instance comgroup with ['a <: comring] 'a poly
op zero = pzero<:'a>
op (+) = padd<:'a>
op ([-]) = pinv<:'a>.
realize addr0.
proof.
(* TODO: error message. *)
move => x (*y*).
(* Top.Logic turned into top... *)
(* TODO: error message. *)
(*rewrite //.*)
(* TODO: wow I just broke something. *)
(* rewrite /padd /pzero. *)
admit.
qed.
realize addrN.
proof.
(* TODO: all truly is broken. *)
(*rewrite /pzero /padd.*)
admit.
qed.
realize addrC by admit.
realize addrA by admit.
instance comring with ['a <: comring] 'a poly
op one = pone<:'a>
op ( * ) = pmul<:'a>.
realize mulr1 by admit.
realize mulrC by admit.
realize mulrA by admit.
realize mulrDl by admit.
instance 'a commodule with ['a <: comring] 'a poly
op ( ** ) = ipmul<:'a>.
realize scalerDl by admit.
realize scalerDr by admit.
(* ==================================================================== *)
(* Misc *)
(* -------------------------------------------------------------------- *)
(* TODO: which instance is kept in memory after this? *)
op bool_enum_alt = [true; false].
instance finite with bool
op enum = bool_enum_alt.
realize enumP.
proof. by case. qed.
type class find_out <: finite = {
axiom rev_enum : rev<:find_out> enum = enum
}.
instance find_out with bool.
realize rev_enum.
proof.
admit.
qed.
(* -------------------------------------------------------------------- *)
(* TODO: some old bug that maybe already is fixed? *)
type class foo = {}.
type class tc = {
op foo : tc -> bool
axiom foo_lemma : forall x, foo x
}.
op foo_int (x : int) = true.
instance tc with int
op foo = foo_int.
realize foo_lemma.
proof. done. qed.
type class ['a <: foo] tc2 <: tc = {
op bar : tc2 -> bool
axiom bar_lemma : forall x, foo x => !bar x
}.
op bar_int (x : int) = false.
instance foo with bool.
instance foo with bool.
instance bool tc2 with int
op bar = bar_int. (* BUG *)
realize bar_lemma.
proof. done. qed.
op foo_2 ['a <: foo, 'b <: 'a tc2] = 0.
(* ==================================================================== *)
(* Old TODO list: 1-3 are done, modulo bugs, 4 is to be done, 5 will be done later. *)
(*
1. typage -> selection des operateurs / inference des instances de tc
2. reduction
3. unification (tactiques)
4. clonage
5. envoi au SMT
1.
Fop :
-(old) path * ty list -> form
-(new) path * (ty * (map tcname -> tcinstance)) list -> form
op ['a <: monoid] (+) : 'a -> 'a -> 'a.
(+)<:int + monoid -> intadd_monoid>
(+)<:int + monoid -> intmul_monoid>
1.1 module de construction des formules avec typage
1.2 utiliser le module ci-dessous
let module M = MkForm(struct let env = env' end) in
1.3 UnionFind avec contraintes de TC
1.4 Overloading:
3 + 4
a. 3 Int.(+) 4
b. 3 Monoid<:int>.(+) 4 (-> instance du dessus -> ignore)
1.5 foo<: int[monoid -> intadd_monoid] >
foo<: int[monoid -> intmul_monoid] >
2. -> Monoid.(+)<:int> -> Int.(+)
3. -> Pb d'unification des op
(+)<: ?[monoid -> ?] > ~ Int.(+)
Mecanisme de resolution des TC
4. -> il faut cloner les TC
5.
a. encodage
record 'a premonoid = {
op zero : 'a
op add : 'a -> 'a -> 'a;
}
pred ['a] ismonoid (m : 'a premonoid) = {
left_id m.zero m.add
}
op ['a <: monoid] foo (x y : 'a) = x + y
->> foo ['a] (m : 'a premonoid) (x y : 'a) = m.add x y
lemma foo ['a <: monoid] P
->> foo ['a] (m : 'a premonoid) : ismonoid m => P
let intmonoid = { zero = 0; add = intadd }
lemma intmonoid_is_monoid : ismonoid int_monoid
b. reduction avant envoi
(+)<: int[monoid -> intadd_monoid > -> Int.(+)
c. ne pas envoyer certaines instances (e.g. int est un groupe)
-> instance [nosmt] e.g.
*)