text \Spartan type theory\ theory Spartan imports Pure "HOL-Eisbach.Eisbach" "HOL-Eisbach.Eisbach_Tools" keywords "Theorem" "Lemma" "Corollary" "Proposition" "Definition" :: thy_goal_stmt and "focus" "\" "\<^item>" "\<^enum>" "~" :: prf_script_goal % "proof" and "congruence" "print_coercions" :: thy_decl and "rhs" "derive" "prems" "vars" :: quasi_command begin section \Prelude\ paragraph \Set up the meta-logic just so.\ paragraph \Notation.\ declare [[eta_contract=false]] text \ Rebind notation for meta-lambdas since we want to use `\` for the object lambdas. Meta-functions now use the binder `fn`. \ setup \ let val typ = Simple_Syntax.read_typ fun mixfix (sy, ps, p) = Mixfix (Input.string sy, ps, p, Position.no_range) in Sign.del_syntax (Print_Mode.ASCII, true) [("_lambda", typ "pttrns \ 'a \ logic", mixfix ("(3%_./ _)", [0, 3], 3))] #> Sign.del_syntax Syntax.mode_default [("_lambda", typ "pttrns \ 'a \ logic", mixfix ("(3\_./ _)", [0, 3], 3))] #> Sign.add_syntax Syntax.mode_default [("_lambda", typ "pttrns \ 'a \ logic", mixfix ("(3fn _./ _)", [0, 3], 3))] end \ syntax "_dollar" :: \logic \ logic \ logic\ (infixr "$" 3) translations "a $ b" \ "a (b)" abbreviation (input) K where "K x \ fn _. x" paragraph \ Deeply embed dependent type theory: meta-type of expressions, and typing judgment. \ typedecl o consts has_type :: \o \ o \ prop\ ("(2_:/ _)" 999) text \Type annotations for type-checking and inference.\ definition anno :: \o \ o \ o\ ("'(_ : _')") where "(a : A) \ a" if "a: A" lemma anno: "a: A \ (a : A): A" by (unfold anno_def) section \Axioms\ subsection \Universes\ typedecl lvl \ \Universe levels\ axiomatization O :: \lvl\ and S :: \lvl \ lvl\ and lt :: \lvl \ lvl \ prop\ (infix "<" 900) where O_min: "O < S i" and lt_S: "i < S i" and lt_trans: "i < j \ j < k \ i < k" axiomatization U :: \lvl \ o\ where Ui_in_Uj: "i < j \ U i: U j" and in_Uj_if_in_Ui: "A: U i \ i < j \ A: U j" lemma Ui_in_USi: "U i: U (S i)" by (rule Ui_in_Uj, rule lt_S) lemma in_USi_if_in_Ui: "A: U i \ A: U (S i)" by (erule in_Uj_if_in_Ui, rule lt_S) subsection \\-type\ axiomatization Pi :: \o \ (o \ o) \ o\ and lam :: \o \ (o \ o) \ o\ and app :: \o \ o \ o\ ("(1_ `_)" [120, 121] 120) syntax "_Pi" :: \idts \ o \ o \ o\ ("(2\_: _./ _)" 30) "_Pi2" :: \idts \ o \ o \ o\ "_lam" :: \idts \ o \ o \ o\ ("(2\_: _./ _)" 30) "_lam2" :: \idts \ o \ o \ o\ translations "\x xs: A. B" \ "CONST Pi A (fn x. _Pi2 xs A B)" "_Pi2 x A B" \ "\x: A. B" "\x: A. B" \ "CONST Pi A (fn x. B)" "\x xs: A. b" \ "CONST lam A (fn x. _lam2 xs A b)" "_lam2 x A b" \ "\x: A. b" "\x: A. b" \ "CONST lam A (fn x. b)" abbreviation Fn (infixr "\" 40) where "A \ B \ \_: A. B" axiomatization where PiF: "\A: U i; \x. x: A \ B x: U i\ \ \x: A. B x: U i" and PiI: "\A: U i; \x. x: A \ b x: B x\ \ \x: A. b x: \x: A. B x" and PiE: "\f: \x: A. B x; a: A\ \ f `a: B a" and beta: "\a: A; \x. x: A \ b x: B x\ \ (\x: A. b x) `a \ b a" and eta: "f: \x: A. B x \ \x: A. f `x \ f" and Pi_cong: "\ \x. x: A \ B x \ B' x; A: U i; \x. x: A \ B x: U j; \x. x: A \ B' x: U j \ \ \x: A. B x \ \x: A. B' x" and lam_cong: "\\x. x: A \ b x \ c x; A: U i\ \ \x: A. b x \ \x: A. c x" subsection \\-type\ axiomatization Sig :: \o \ (o \ o) \ o\ and pair :: \o \ o \ o\ ("(2<_,/ _>)") and SigInd :: \o \ (o \ o) \ (o \ o) \ (o \ o \ o) \ o \ o\ syntax "_Sum" :: \idt \ o \ o \ o\ ("(2\_: _./ _)" 20) translations "\x: A. B" \ "CONST Sig A (fn x. B)" abbreviation Prod (infixl "\" 60) where "A \ B \ \_: A. B" abbreviation "and" (infixl "\" 60) where "A \ B \ A \ B" axiomatization where SigF: "\A: U i; \x. x: A \ B x: U i\ \ \x: A. B x: U i" and SigI: "\\x. x: A \ B x: U i; a: A; b: B a\ \ : \x: A. B x" and SigE: "\ p: \x: A. B x; A: U i; \x. x : A \ B x: U j; \p. p: \x: A. B x \ C p: U k; \x y. \x: A; y: B x\ \ f x y: C \ \ SigInd A (fn x. B x) (fn p. C p) f p: C p" and Sig_comp: "\ a: A; b: B a; \x. x: A \ B x: U i; \p. p: \x: A. B x \ C p: U i; \x y. \x: A; y: B x\ \ f x y: C \ \ SigInd A (fn x. B x) (fn p. C p) f \ f a b" and Sig_cong: "\ \x. x: A \ B x \ B' x; A: U i; \x. x : A \ B x: U j; \x. x : A \ B' x: U j \ \ \x: A. B x \ \x: A. B' x" section \Infrastructure\ ML_file \lib.ML\ ML_file \context_tactical.ML\ subsection \Proof commands\ ML_file \focus.ML\ named_theorems typechk ML_file \goals.ML\ subsection \Congruence automation\ consts "rhs" :: \'a\ ("..") ML_file \congruence.ML\ subsection \Proof methods and type-checking/inference\ named_theorems form and intro and intros and comp \ \`intros` stores the introduction rule variants used by the `intro` and `intros` methods.\ ML_file \elimination.ML\ \ \elimination rules\ ML_file \cases.ML\ \ \case reasoning rules\ lemmas [form] = PiF SigF and [intro] = PiI SigI and [intros] = PiI[rotated] SigI and [elim "?f"] = PiE and [elim "?p"] = SigE and [comp] = beta Sig_comp and [cong] = Pi_cong lam_cong Sig_cong ML_file \typechecking.ML\ ML_file \tactics.ML\ method_setup typechk = \Scan.succeed (K (CONTEXT_METHOD ( CHEADGOAL o Types.check_infer)))\ method_setup known = \Scan.succeed (K (CONTEXT_METHOD ( CHEADGOAL o Types.known_ctac)))\ method_setup rule = \Attrib.thms >> (fn ths => K (CONTEXT_METHOD ( CHEADGOAL o SIDE_CONDS (rule_ctac ths))))\ method_setup rules = \Attrib.thms >> (fn ths => K (CONTEXT_METHOD ( CREPEAT o CHEADGOAL o SIDE_CONDS (rule_ctac ths))))\ method_setup dest = \Scan.lift (Scan.option (Args.parens Parse.int)) -- Attrib.thms >> (fn (n_opt, ths) => K (CONTEXT_METHOD ( CHEADGOAL o SIDE_CONDS (dest_ctac n_opt ths))))\ method_setup intro = \Scan.succeed (K (CONTEXT_METHOD ( CHEADGOAL o SIDE_CONDS (intro_ctac))))\ method_setup intros = \Scan.succeed (K (CONTEXT_METHOD ( CHEADGOAL o SIDE_CONDS (CREPEAT o intro_ctac))))\ method_setup elim = \Scan.repeat Args.term >> (fn tms => K (CONTEXT_METHOD ( CHEADGOAL o SIDE_CONDS (elim_ctac tms))))\ method elims = elim+ method_setup cases = \Args.term >> (fn tm => K (CONTEXT_METHOD ( CHEADGOAL o SIDE_CONDS (cases_ctac tm))))\ method facts = fact+ subsection \Reflexivity\ named_theorems refl method refl = (rule refl) subsection \Trivial proofs (modulo automatic discharge of side conditions)\ method_setup this = \Scan.succeed (K (CONTEXT_METHOD (fn facts => CHEADGOAL (SIDE_CONDS (CONTEXT_TACTIC' (fn ctxt => resolve_tac ctxt facts)) facts))))\ subsection \Rewriting\ \ \\subst\ method\ ML_file \~~/src/Tools/misc_legacy.ML\ ML_file \~~/src/Tools/IsaPlanner/isand.ML\ ML_file \~~/src/Tools/IsaPlanner/rw_inst.ML\ ML_file \~~/src/Tools/IsaPlanner/zipper.ML\ ML_file \eqsubst.ML\ \ \\rewrite\ method\ consts rewrite_HOLE :: "'a::{}" ("\") lemma eta_expand: fixes f :: "'a::{} \ 'b::{}" shows "f \ fn x. f x" . lemma rewr_imp: assumes "PROP A \ PROP B" shows "(PROP A \ PROP C) \ (PROP B \ PROP C)" apply (Pure.rule Pure.equal_intr_rule) apply (drule equal_elim_rule2[OF assms]; assumption) apply (drule equal_elim_rule1[OF assms]; assumption) done lemma imp_cong_eq: "(PROP A \ (PROP B \ PROP C) \ (PROP B' \ PROP C')) \ ((PROP B \ PROP A \ PROP C) \ (PROP B' \ PROP A \ PROP C'))" apply (Pure.intro Pure.equal_intr_rule) apply (drule (1) cut_rl; drule Pure.equal_elim_rule1 Pure.equal_elim_rule2; assumption)+ apply (drule Pure.equal_elim_rule1 Pure.equal_elim_rule2; assumption)+ done ML_file \~~/src/HOL/Library/cconv.ML\ ML_file \rewrite.ML\ \ \\reduce\ computes terms via judgmental equalities\ setup \map_theory_simpset (fn ctxt => ctxt addSolver (mk_solver "" (fn ctxt' => NO_CONTEXT_TACTIC ctxt' o Types.check_infer (Simplifier.prems_of ctxt'))))\ method reduce uses add = changed \repeat_new \(simp add: comp add | sub comp); typechk?\\ subsection \Implicits\ text \ \?\ is used to mark implicit arguments in definitions, while \{}\ is expanded immediately for elaboration in statements. \ consts iarg :: \'a\ ("?") hole :: \'b\ ("{}") ML_file \implicits.ML\ attribute_setup implicit = \Scan.succeed Implicits.implicit_defs_attr\ ML \val _ = Context.>> (Syntax_Phases.term_check 1 "" Implicits.make_holes)\ text \Automatically insert inhabitation judgments where needed:\ syntax inhabited :: \o \ prop\ ("(_)") translations "inhabited A" \ "CONST has_type {} A" text \Implicit lambdas\ definition lam_i where [implicit]: "lam_i f \ lam ? f" syntax "_lam_i" :: \idts \ o \ o\ ("(2\_./ _)" 30) "_lam_i2" :: \idts \ o \ o\ translations "\x xs. b" \ "CONST lam_i (fn x. _lam_i2 xs b)" "_lam_i2 x b" \ "\x. b" "\x. b" \ "CONST lam_i (fn x. b)" subsection \Lambda coercion\ \ \Coerce object lambdas to meta-lambdas\ abbreviation (input) lambda :: \o \ o \ o\ where "lambda f \ fn x. f `x" ML_file \~~/src/Tools/subtyping.ML\ declare [[coercion_enabled, coercion lambda]] translations "f x" \ "f `x" section \Functions\ lemma eta_exp: assumes "f: \x: A. B x" shows "f \ \x: A. f x" by (rule eta[symmetric]) lemma refine_codomain: assumes "A: U i" "f: \x: A. B x" "\x. x: A \ f `x: C x" shows "f: \x: A. C x" by (subst eta_exp) lemma lift_universe_codomain: assumes "A: U i" "f: A \ U j" shows "f: A \ U (S j)" using in_USi_if_in_Ui[of "f {}"] by (rule refine_codomain) subsection \Function composition\ definition "funcomp A g f \ \x: A. g `(f `x)" syntax "_funcomp" :: \o \ o \ o \ o\ ("(2_ \\<^bsub>_\<^esub>/ _)" [111, 0, 110] 110) translations "g \\<^bsub>A\<^esub> f" \ "CONST funcomp A g f" lemma funcompI [typechk]: assumes "A: U i" "B: U i" "\x. x: B \ C x: U i" "f: A \ B" "g: \x: B. C x" shows "g \\<^bsub>A\<^esub> f: \x: A. C (f x)" unfolding funcomp_def by typechk lemma funcomp_assoc [comp]: assumes "f: A \ B" "g: B \ C" "h: \x: C. D x" "A: U i" shows "(h \\<^bsub>B\<^esub> g) \\<^bsub>A\<^esub> f \ h \\<^bsub>A\<^esub> g \\<^bsub>A\<^esub> f" unfolding funcomp_def by reduce lemma funcomp_lambda_comp [comp]: assumes "A: U i" "\x. x: A \ b x: B" "\x. x: B \ c x: C x" shows "(\x: B. c x) \\<^bsub>A\<^esub> (\x: A. b x) \ \x: A. c (b x)" unfolding funcomp_def by reduce lemma funcomp_apply_comp [comp]: assumes "f: A \ B" "g: \x: B. C x" "x: A" "A: U i" "B: U i" "\x y. x: B \ C x: U i" shows "(g \\<^bsub>A\<^esub> f) x \ g (f x)" unfolding funcomp_def by reduce text \Notation:\ definition funcomp_i (infixr "\" 120) where [implicit]: "funcomp_i g f \ g \\<^bsub>?\<^esub> f" translations "g \ f" \ "g \\<^bsub>A\<^esub> f" subsection \Identity function\ abbreviation id where "id A \ \x: A. x" lemma id_type[typechk]: "A: U i \ id A: A \ A" and id_comp [comp]: "x: A \ (id A) x \ x" \ \for the occasional manual rewrite\ by reduce+ lemma id_left [comp]: assumes "f: A \ B" "A: U i" "B: U i" shows "(id B) \\<^bsub>A\<^esub> f \ f" by (subst eta_exp[of f]) (reduce, rule eta) lemma id_right [comp]: assumes "f: A \ B" "A: U i" "B: U i" shows "f \\<^bsub>A\<^esub> (id A) \ f" by (subst eta_exp[of f]) (reduce, rule eta) lemma id_U [typechk]: "id (U i): U i \ U i" using Ui_in_USi by typechk section \Pairs\ definition "fst A B \ \p: \x: A. B x. SigInd A B (fn _. A) (fn x y. x) p" definition "snd A B \ \p: \x: A. B x. SigInd A B (fn p. B (fst A B p)) (fn x y. y) p" lemma fst_type [typechk]: assumes "A: U i" "\x. x: A \ B x: U i" shows "fst A B: (\x: A. B x) \ A" unfolding fst_def by typechk lemma fst_comp [comp]: assumes "a: A" "b: B a" "A: U i" "\x. x: A \ B x: U i" shows "fst A B \ a" unfolding fst_def by reduce lemma snd_type [typechk]: assumes "A: U i" "\x. x: A \ B x: U i" shows "snd A B: \p: \x: A. B x. B (fst A B p)" unfolding snd_def by typechk reduce lemma snd_comp [comp]: assumes "a: A" "b: B a" "A: U i" "\x. x: A \ B x: U i" shows "snd A B \ b" unfolding snd_def by reduce subsection \Notation\ definition fst_i ("fst") where [implicit]: "fst \ Spartan.fst ? ?" definition snd_i ("snd") where [implicit]: "snd \ Spartan.snd ? ?" translations "fst" \ "CONST Spartan.fst A B" "snd" \ "CONST Spartan.snd A B" subsection \Projections\ Lemma fst [typechk]: assumes "p: \x: A. B x" "A: U i" "\x. x: A \ B x: U i" shows "fst p: A" by typechk Lemma snd [typechk]: assumes "p: \x: A. B x" "A: U i" "\x. x: A \ B x: U i" shows "snd p: B (fst p)" by typechk method fst for p::o = rule fst[of p] method snd for p::o = rule snd[of p] subsection \Properties of \\ Lemma (derive) Sig_dist_exp: assumes "p: \x: A. B x \ C x" "A: U i" "\x. x: A \ B x: U i" "\x. x: A \ C x: U i" shows "(\x: A. B x) \ (\x: A. C x)" apply (elim p) focus vars x y apply intro \ apply intro apply assumption apply (fst y) done \ apply intro apply assumption apply (snd y) done done done end