From d70da13b7fd36509c1d843d139a0b99c6acb8cc6 Mon Sep 17 00:00:00 2001 From: Josh Chen Date: Tue, 5 Feb 2019 18:15:58 +0100 Subject: Type inference setup begun - first use-case for function composition. --- HoTT_Base.thy | 57 ++++++------------------------------- Prod.thy | 31 +++++++++++--------- typing.ML | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 61 deletions(-) create mode 100644 typing.ML diff --git a/HoTT_Base.thy b/HoTT_Base.thy index a5280ce..aa13815 100644 --- a/HoTT_Base.thy +++ b/HoTT_Base.thy @@ -3,11 +3,11 @@ Isabelle/HoTT: Foundational definitions and notation Jan 2019 This file is the starting point of the Isabelle/HoTT object logic, and contains the basic setup and definitions. -Among other things, it defines: +Among other things, it: -* Containers for storing type information of object-level terms. -* The universe hierarchy and its governing rules. -* Named theorems for later use by proof methods. +* Sets up object-level type inference functionality (via typing.ML). +* Defines the universe hierarchy and its governing rules. +* Defines named theorems for later use by proof methods. ********) @@ -20,48 +20,9 @@ section \Terms and typing\ typedecl t \ \Type of object-logic terms (which includes the types)\ -consts has_type :: "[t, t] \ prop" \ \The judgment coercion\ +judgment has_type :: "[t, t] \ prop" ("(3_:/ _)") -text \ -We create a dedicated container in which to store object-level typing information whenever a typing judgment that does not depend on assumptions is proved. -\ - -ML \ -signature TYPINGS = -sig - val get: term -> term -end - -structure Typings: TYPINGS = -struct - -structure Typing_Data = Theory_Data -( - type T = term Symtab.table - val empty = Symtab.empty - val extend = I - - fun merge (tbl, tbl') = - let - val key_vals = map (Symtab.lookup_key tbl') (Symtab.keys tbl') - val updates = map (fn SOME kv => Symtab.update kv) key_vals - fun f u t = u t - in fold f updates tbl end -) - -fun get tm = - case Symtab.lookup (Typing_Data.get @{theory}) (Syntax.string_of_term @{context} tm) of - SOME tm' => tm' - | NONE => raise Fail "No typing information available" - -end -\ - -syntax "_has_type" :: "[t, t] \ prop" ("3(_:/ _)") - -parse_translation \ - -\ +ML_file "typing.ML" section \Universes\ @@ -85,13 +46,13 @@ declare axiomatization U :: "ord \ t" where - U_hierarchy: "i < j \ U i: U j" and + U_hierarchy: "i < j \ U i: U j" and U_cumulative: "\A: U i; i < j\ \ A: U j" and U_cumulative': "\A: U i; i \ j\ \ A: U j" text \ -Using method @{method rule} with @{thm U_cumulative} is unsafe, if applied blindly it will very easily lead to non-termination. -Instead use @{method elim}, or instantiate @{thm U_cumulative} suitably. +Using method @{method rule} with @{thm U_cumulative} and @{thm U_cumulative'} is unsafe: if applied blindly it will very easily lead to non-termination. +Instead use @{method elim}, or instantiate the rules suitably. @{thm U_cumulative'} is an alternative rule used by the method @{theory_text cumulativity} in @{file HoTT_Methods.thy}. \ diff --git a/Prod.thy b/Prod.thy index 68c9405..4c572ce 100644 --- a/Prod.thy +++ b/Prod.thy @@ -79,32 +79,37 @@ syntax "_compose" :: "[t, t] \ t" (infixr "o" 110) parse_translation \ let fun compose_tr ctxt tms = let - val f::g::_ = tms; - fun domain f = @{term "A :: t"} + val g :: f :: _ = tms |> map (Typing.tm_of_ptm ctxt) + val dom = + case Typing.get_typing f (Typing.typing_assms ctxt) of + SOME (Const ("Prod.Prod", _) $ T $ _) => T + | SOME _ => Exn.error "Can't compose with a non-function" + | NONE => Exn.error "Cannot infer domain of composition—please state this explicitly" in - @{const compose} $ (domain f) $ f $ g + @{const compose} $ dom $ g $ f end in [("_compose", compose_tr)] end \ -ML_val \ -Proof_Context.get_thms @{context} "compose_def" -\ - lemma compose_assoc: - assumes "A: U i" "f: A \ B" "g: B \ C" "h: TT x: C. D x" + assumes "A: U i" "f: A \ B" "g: B \ C" "h: TT x: C. D x" "(,\\(x: A). b x): TT x: A. D x" shows "(h o g) o f \ h o (g o f)" -ML_prf \ -@{thms assms}; -\ (* (derive lems: assms Prod_intro_eq) *) +sorry lemma compose_comp: assumes "A: U i" and "\x. x: A \ b x: B" and "\x. x: B \ c x: C x" - shows "(\<^bold>\x. c x) \ (\<^bold>\x. b x) \ \<^bold>\x. c (b x)" -by (derive lems: assms Prod_intro_eq) + shows "(,\\x: B. c x) o (,\\x: A. b x) \ ,\\x: A. c (b x)" +ML_prf \ +Assumption.all_assms_of @{context}; +nth (Assumption.all_assms_of @{context}) 1 |> Thm.term_of; +Assumption.all_prems_of @{context}; +nth (Assumption.all_prems_of @{context}) 0 |> Thm.prop_of; +typing_assms @{context} +\ +(*by (derive lems: assms Prod_intro_eq)*) abbreviation id :: "t \ t" where "id A \ ,\\x: A. x" diff --git a/typing.ML b/typing.ML new file mode 100644 index 0000000..bfe8409 --- /dev/null +++ b/typing.ML @@ -0,0 +1,91 @@ +(******** +Isabelle/HoTT: typing.ML +Feb 2019 + +Functionality for object-level type inference. + +********) + +signature TYPING = +sig + type jmt = term + val term_of_jmt: jmt -> term + val type_of_jmt: jmt -> term + val typing_assms: Proof.context -> jmt list + val get_typing: term -> jmt list -> term option + val get_global_typing: theory -> Proof.context -> term -> term option + val tm_of_ptm: Proof.context -> term -> term +end + +structure Typing: TYPING = +struct + +type jmt = term + +(* Functions to extract a and A from propositions "a: A" *) +fun term_of_jmt (@{const has_type} $ t $ _) = t + | term_of_jmt _ = Exn.error "Not a typing judgment" + +fun type_of_jmt (@{const has_type} $ _ $ T) = T + | type_of_jmt _ = Exn.error "Not a typing judgment" + +(* Get the typing assumptions in the current context *) +fun typing_assms ctxt = + let + fun is_typing_jmt (@{const has_type} $ _ $ _) = true + | is_typing_jmt _ = false + in + Assumption.all_prems_of ctxt |> map Thm.prop_of |> filter is_typing_jmt + end + +(* Search for a term typing in a list of judgments*) +fun get_typing tm jmts = + let val find_type = + fn jmt => if Term.aconv_untyped (tm, term_of_jmt jmt) then SOME (type_of_jmt jmt) else NONE + in get_first find_type jmts end + +(* Private storage space for global typing data *) +structure Typing_Data = Theory_Data +( + type T = term Symtab.table + val empty = Symtab.empty + val extend = I + + fun merge (tbl, tbl') = + let + val key_vals = map (Symtab.lookup_key tbl') (Symtab.keys tbl') + val updates = map (fn SOME kv => Symtab.update kv) key_vals + fun f u t = u t + in fold f updates tbl end +) + +(* Accessor for the above data *) +fun get_global_typing thy ctxt tm = Symtab.lookup (Typing_Data.get thy) (Syntax.string_of_term ctxt tm) + +(* Convert a Pure pre-term to an unchecked Pure term *) +fun tm_of_ptm ctxt ptm = + let val ptm = Term_Position.strip_positions ptm + in + (case ptm of + Const ("_constrain", _) $ Free (t, _) $ (Const ("\<^type>fun", _) $ Const(n1, _) $ Const (n2, _)) => + let + val typ1 = unprefix "\<^type>" n1 + val typ2 = unprefix "\<^type>" n2 + val typ = typ1 ^ "\" ^ typ2 |> Syntax.read_typ ctxt + in Free (t, typ) end + | Const ("_constrain", _) $ Free (t, _) $ Const (T, _) => + Free (t, Syntax.read_typ ctxt (unprefix "\<^type>" T)) + | ptm1 $ ptm2 => + (tm_of_ptm ctxt ptm1) $ (tm_of_ptm ctxt ptm2) + | Const (t, T) => + let val t' = + unprefix "\<^const>" t handle Fail "unprefix" => + unprefix "\<^type>" t handle Fail "unprefix" => + t + in Const (t', T) end + | Abs (t, T, ptm') => + Abs (t, T, tm_of_ptm ctxt ptm') + | t => t) + end + +end -- cgit v1.2.3