(* Title: Pure/sorts.ML Author: Markus Wenzel and Stefan Berghofer, TU Muenchen
The order-sorted algebra of type classes.
Classes denote (possibly empty) collections of types that are partially ordered by class inclusion. They are represented symbolically by strings.
Sorts are intersections of finitely many classes. They are represented by lists of classes. Normal forms of sorts are sorted lists of minimal classes (wrt. current class inclusion).
*)
signature SORTS = sig val make: sort list -> sort Ord_List.T val subset: sort Ord_List.T * sort Ord_List.T -> bool val union: sort Ord_List.T -> sort Ord_List.T -> sort Ord_List.T val unions: sort Ord_List.T list -> sort Ord_List.T val subtract: sort Ord_List.T -> sort Ord_List.T -> sort Ord_List.T val remove_sort: sort -> sort Ord_List.T -> sort Ord_List.T val insert_sort: sort -> sort Ord_List.T -> sort Ord_List.T val insert_typ: typ -> sort Ord_List.T -> sort Ord_List.T val insert_typs: typ list -> sort Ord_List.T -> sort Ord_List.T val insert_term: term -> sort Ord_List.T -> sort Ord_List.T val insert_terms: term list -> sort Ord_List.T -> sort Ord_List.T type algebra val classes_of: algebra -> serial Graph.T val arities_of: algebra -> (class * sort list) list Symtab.table val all_classes: algebra -> class list val super_classes: algebra -> class -> class list val cert_class: algebra -> class -> class val cert_sort: algebra -> sort -> sort val class_less: algebra -> class * class -> bool val class_le: algebra -> class * class -> bool val sort_eq: algebra -> sort * sort -> bool val sort_le: algebra -> sort * sort -> bool val sorts_le: algebra -> sort list * sort list -> bool val inter_sort: algebra -> sort * sort -> sort val minimize_sort: algebra -> sort -> sort val complete_sort: algebra -> sort -> sort val add_class: Context.generic -> class * class list -> algebra -> algebra val add_classrel: Context.generic -> class * class -> algebra -> algebra val add_arities: Context.generic -> string * (class * sort list) list -> algebra -> algebra val empty_algebra: algebra val merge_algebra: Context.generic -> algebra * algebra -> algebra val dest_algebra: algebra list -> algebra ->
{classrel: (class * class list) list,
arities: (string * sort list * class) list} val subalgebra: Context.generic -> (class -> bool) -> (class * string -> sort listoption)
-> algebra -> (sort -> sort) * algebra type class_error val class_error: Context.generic -> class_error -> string
exception CLASS_ERROR of class_error val has_instance: algebra -> string -> sort -> bool val mg_domain: algebra -> string -> sort -> sort list(*exception CLASS_ERROR*) val meet_sort: algebra -> typ * sort
-> sort Vartab.table -> sort Vartab.table (*exception CLASS_ERROR*) val meet_sort_typ: algebra -> typ * sort -> typ -> typ (*exception CLASS_ERROR*) val of_sort: algebra -> typ * sort -> bool val of_sort_derivation: algebra ->
{class_relation: typ -> bool -> 'a * class -> class -> 'a,
type_constructor: string * typ list -> ('a * class) list list -> class -> 'a,
type_variable: typ -> ('a * class) list} ->
typ * sort -> 'a list (*exception CLASS_ERROR*) val classrel_derivation: algebra ->
('a * class -> class -> 'a) -> 'a * class -> class -> 'a (*exception CLASS_ERROR*) val witness_sorts: algebra -> stringlist ->
(typ * sort) list -> sort Ord_List.T ->
(typ * sort) list * sort Ord_List.T end;
structure Sorts: SORTS = struct
(** ordered lists of sorts **)
val make = Ord_List.make Term_Ord.sort_ord; val subset = Ord_List.subset Term_Ord.sort_ord; val union = Ord_List.union Term_Ord.sort_ord; val unions = Ord_List.unions Term_Ord.sort_ord; val subtract = Ord_List.subtract Term_Ord.sort_ord;
val remove_sort = Ord_List.remove Term_Ord.sort_ord; val insert_sort = Ord_List.insert Term_Ord.sort_ord;
fun insert_typ (TFree (_, S)) Ss = insert_sort S Ss
| insert_typ (TVar (_, S)) Ss = insert_sort S Ss
| insert_typ (Type (_, Ts)) Ss = insert_typs Ts Ss and insert_typs [] Ss = Ss
| insert_typs (T :: Ts) Ss = insert_typs Ts (insert_typ T Ss);
fun insert_term (Const (_, T)) Ss = insert_typ T Ss
| insert_term (Free (_, T)) Ss = insert_typ T Ss
| insert_term (Var (_, T)) Ss = insert_typ T Ss
| insert_term (Bound _) Ss = Ss
| insert_term (Abs (_, T, t)) Ss = insert_term t (insert_typ T Ss)
| insert_term (t $ u) Ss = insert_term t (insert_term u Ss);
fun insert_terms [] Ss = Ss
| insert_terms (t :: ts) Ss = insert_terms ts (insert_term t Ss);
(** order-sorted algebra **)
(* classes: graph representing class declarations together with proper subclass relation, which needs to be transitive and acyclic.
arities: table of association lists of all type arities; (t, ars) means that type constructor t has the arities ars; an element (c, Ss) of ars represents the arity t::(Ss)c. "Coregularity" of the arities structure requires that for any two declarations t::(Ss1)c1 and t::(Ss2)c2 such that c1 <= c2 holds Ss1 <= Ss2.
*)
datatype algebra = Algebra of
{classes: serial Graph.T,
arities: (class * sort list) list Symtab.table};
fun classes_of (Algebra {classes, ...}) = classes; fun arities_of (Algebra {arities, ...}) = arities;
fun map_classes f (Algebra {classes, arities}) = make_algebra (f classes, arities); fun map_arities f (Algebra {classes, arities}) = make_algebra (classes, f arities);
(* classes *)
fun all_classes (Algebra {classes, ...}) = Graph.all_preds classes (Graph.maximals classes);
val super_classes = Graph.immediate_succs o classes_of;
fun cert_class (Algebra {classes, ...}) c = if Graph.defined classes c then c elseraiseTYPE ("Undeclared class: " ^ quote c, [], []);
fun cert_sort algebra S = (List.app (ignore o cert_class algebra) S; S);
(* class relations *)
val class_less : algebra -> class * class -> bool = Graph.is_edge o classes_of; fun class_le algebra (c1, c2) = c1 = c2 orelse class_less algebra (c1, c2);
fun inter_class algebra c S = let fun intr [] = [c]
| intr (S' as c' :: c's) = if class_le algebra (c', c) then S' elseif class_le algebra (c, c') then intr c's else c' :: intr c's in intr S end;
fun minimize_sort _ [] = []
| minimize_sort _ (S as [_]) = S
| minimize_sort algebra S = filter (fn c => not (exists (fn c' => class_less algebra (c', c)) S)) S
|> sort_distinct string_ord;
fun complete_sort algebra =
Graph.all_succs (classes_of algebra) o minimize_sort algebra;
(** build algebras **)
(* classes *)
fun err_dup_class c = error ("Duplicate declaration of class: " ^ quote c);
fun err_cyclic_classes context css =
error (cat_lines (map (fn cs => "Cycle in class relation: " ^ Syntax.string_of_classrel (Syntax.init_pretty context) cs) css));
fun add_class context (c, cs) = map_classes (fn classes => let val classes' = classes |> Graph.new_node (c, serial ()) handle Graph.DUP dup => err_dup_class dup; val classes'' = classes' |> fold Graph.add_edge_trans_acyclic (map (pair c) cs) handle Graph.CYCLES css => err_cyclic_classes context css; in classes''end);
fun err_conflict context t cc (c, Ss) (c', Ss') = letval ctxt = Syntax.init_pretty context in
error ("Conflict of type arities" ^ for_classes ctxt cc ^ ":\n " ^
Syntax.string_of_arity ctxt (t, Ss, [c]) ^ " and\n " ^
Syntax.string_of_arity ctxt (t, Ss', [c'])) end;
fun coregular context algebra t (c, Ss) ars = let fun conflict (c', Ss') = if class_le algebra (c, c') andalso not (sorts_le algebra (Ss, Ss')) then
SOME ((c, c'), (c', Ss')) elseif class_le algebra (c', c) andalso not (sorts_le algebra (Ss', Ss)) then
SOME ((c', c), (c', Ss')) else NONE; in
(case get_first conflict ars of
SOME ((c1, c2), (c', Ss')) => err_conflict context t (SOME (c1, c2)) (c, Ss) (c', Ss')
| NONE => (c, Ss) :: ars) end;
fun insert context algebra t (c, Ss) ars =
(case AList.lookup (op =) ars c of
NONE => coregular context algebra t (c, Ss) ars
| SOME Ss' => if sorts_le algebra (Ss, Ss') then ars elseif sorts_le algebra (Ss', Ss) then coregular context algebra t (c, Ss) (remove (op =) (c, Ss') ars) else err_conflict context t NONE (c, Ss) (c, Ss'));
in
fun insert_ars context algebra t = fold_rev (insert context algebra t);
fun insert_complete_ars context algebra (t, ars) arities = letval ars' =
Symtab.lookup_list arities t
|> fold_rev (insert_ars context algebra t) (map (complete algebra) ars); in Symtab.update (t, ars') arities end;
fun subalgebra context P sargs (algebra as Algebra {classes, arities}) = let val restrict_sort = minimize_sort algebra o filter P o Graph.all_succs classes; fun restrict_arity t (c, Ss) = if P c then
(case sargs (c, t) of
SOME sorts =>
SOME (c, Ss |> map2 (curry (inter_sort algebra)) sorts |> map restrict_sort)
| NONE => NONE) else NONE; val classes' = classes |> Graph.restrict P; val arities' = arities |> Symtab.map (map_filter o restrict_arity); in (restrict_sort, rebuild_arities context (make_algebra (classes', arities'))) end;
(** sorts of types **)
(* errors -- performance tuning via delayed message composition *)
datatype class_error =
No_Classrel of class * class |
No_Arity ofstring * class |
No_Subsort of sort * sort;
fun class_error context = letval ctxt = Syntax.init_pretty context in
fn No_Classrel (c1, c2) => "No class relation " ^ Syntax.string_of_classrel ctxt [c1, c2]
| No_Arity (a, c) => "No type arity " ^ Syntax.string_of_arity ctxt (a, [], [c])
| No_Subsort (S1, S2) => "Cannot derive subsort relation " ^
Syntax.string_of_sort ctxt S1 ^ " < " ^ Syntax.string_of_sort ctxt S2 end;
exception CLASS_ERROR of class_error;
(* instances *)
fun has_instance algebra a =
forall (AList.defined (op =) (Symtab.lookup_list (arities_of algebra) a));
fun mg_domain algebra a S = let val ars = Symtab.lookup_list (arities_of algebra) a; fun dom c =
(case AList.lookup (op =) ars c of
NONE => raise CLASS_ERROR (No_Arity (a, c))
| SOME Ss => Ss); fun dom_inter c Ss = ListPair.map (inter_sort algebra) (dom c, Ss); in
(case S of
[] => raise Fail "Unknown domain of empty intersection"
| c :: cs => fold dom_inter cs (dom c)) end;
(* meet_sort *)
fun meet_sort algebra = let fun inters S S' = inter_sort algebra (S, S'); fun meet _ [] = I
| meet (TFree (_, S)) S' = if sort_le algebra (S, S') then I elseraise CLASS_ERROR (No_Subsort (S, S'))
| meet (TVar (v, S)) S' = if sort_le algebra (S, S') then I else Vartab.map_default (v, S) (inters S')
| meet (Type (a, Ts)) S = fold2 meet Ts (mg_domain algebra a S); in uncurry meet end;
fun meet_sort_typ algebra (T, S) = letval tab = Vartab.build (meet_sort algebra (T, S)); in Term.map_type_tvar (fn (v, _) => TVar (v, (the o Vartab.lookup tab) v)) end;
(* of_sort *)
fun of_sort algebra = let fun ofS (_, []) = true
| ofS (TFree (_, S), S') = sort_le algebra (S, S')
| ofS (TVar (_, S), S') = sort_le algebra (S, S')
| ofS (Type (a, Ts), S) = letval Ss = mg_domain algebra a S in
ListPair.all ofS (Ts, Ss) endhandle CLASS_ERROR _ => false; in ofS end;
(* animating derivations *)
fun of_sort_derivation algebra {class_relation, type_constructor, type_variable} = let val arities = arities_of algebra;
fun weaken T D1 S2 = letval S1 = map snd D1 in if S1 = S2 thenmap fst D1 else
S2 |> map (fn c2 =>
(case D1 |> filter (fn (_, c1) => class_le algebra (c1, c2)) of
[d1] => class_relation T true d1 c2
| (d1 :: _ :: _) => class_relation T false d1 c2
| [] => raise CLASS_ERROR (No_Subsort (S1, S2)))) end;
fun derive (_, []) = []
| derive (Type (a, Us), S) = let val Ss = mg_domain algebra a S; val dom = map2 (fn U => fn S => derive (U, S) ~~ S) Us Ss; in
S |> map (fn c => let val Ss' = the (AList.lookup (op =) (Symtab.lookup_list arities a) c); val dom' = map (fn ((U, d), S') => weaken U d S' ~~ S') ((Us ~~ dom) ~~ Ss'); in type_constructor (a, Us) dom' c end) end
| derive (T, S) = weaken T (type_variable T) S; in derive end;
fun witness_sorts algebra ground_types hyps sorts = let fun le S1 S2 = sort_le algebra (S1, S2); fun get S2 (T, S1) = if le S1 S2 then SOME (T, S2) else NONE; fun mg_dom t S = SOME (mg_domain algebra t S) handle CLASS_ERROR _ => NONE;
fun witn_sort _ [] solved_failed = (SOME (propT, []), solved_failed)
| witn_sort path S (solved, failed) = ifexists (le S) failed then (NONE, (solved, failed)) else
(case get_first (get S) solved of
SOME w => (SOME w, (solved, failed))
| NONE =>
(case get_first (get S) hyps of
SOME w => (SOME w, (w :: solved, failed))
| NONE => witn_types path ground_types S (solved, failed)))
and witn_sorts path x = fold_map (witn_sort path) x
and witn_types _ [] S (solved, failed) = (NONE, (solved, S :: failed))
| witn_types path (t :: ts) S solved_failed =
(case mg_dom t S of
SOME SS => (*do not descend into stronger args (achieving termination)*) ifexists (fn D => le D S orelse exists (le D) path) SS then
witn_types path ts S solved_failed else letval (ws, (solved', failed')) = witn_sorts (S :: path) SS solved_failed in if forall is_some ws then letval w = (Type (t, map (#1 o the) ws), S) in (SOME w, (w :: solved', failed')) end else witn_types path ts S (solved', failed') end
| NONE => witn_types path ts S solved_failed);
val witnessed = map_filter I (#1 (witn_sorts [] sorts ([], []))); val non_witnessed = fold (remove_sort o #2) witnessed sorts; in (witnessed, non_witnessed) end;
end;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.17Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.