theory Smolka_AI imports Main begin section ‹AI-Authored proof formalization of the roundtrip algorithm› text ‹ Formalization of the Smolka-Blanchette printing--parsing roundtrip algorithm for Isabelle. The algorithm takes a fully-typed term and selects a locally minimal and complete set of type annotations so the term can be unambiguously re-parsed via Hindley--Milner type inference. › subsection ‹Types and Type Substitutions› text ‹Types are built from type variables and type constructors with a fixed arity (implicit in the list length).› datatype ty = TVar string | TCons string "ty list" text ‹We define the function type constructor as a distinguished binary constructor.› definition fun_ty :: "ty ⇒ ty ⇒ ty" (infixr "→" 65) where "fun_ty τ⇩1 τ⇩2 = TCons ''fun'' [τ⇩1, τ⇩2]" text ‹Type variables occurring in a type.› fun tvars_ty :: "ty ⇒ string set" where "tvars_ty (TVar v) = {v}" | "tvars_ty (TCons _ ts) = ⋃(set (map tvars_ty ts))" text ‹Definition (Type Substitution). A type substitution is a function from variable names to types. It extends homomorphically to types.› fun subst_ty :: "(string ⇒ ty) ⇒ ty ⇒ ty" where "subst_ty σ (TVar v) = σ v" | "subst_ty σ (TCons k ts) = TCons k (map (subst_ty σ) ts)" text ‹The arrow type ‹τ → τ› is strictly larger than ‹τ›, hence ‹τ → τ ≠ τ›. This is used in the minimality proof. The proof uses the built-in ‹size› function from the datatype package.› lemma arrow_neq_self: "τ → τ ≠ τ" proof assume "τ → τ = τ" then have "size (τ → τ) = size τ" by simp then show False by (simp add: fun_ty_def) qed text ‹Lemma (Uniqueness of Type Matching). If two substitutions agree when applied to a type, they agree on all type variables of that type.› lemma unique_type_match: "subst_ty σ⇩1 τ = subst_ty σ⇩2 τ ⟹ α ∈ tvars_ty τ ⟹ σ⇩1 α = σ⇩2 α" by (induction τ) auto text ‹Substitution on type variables: the domain is precisely \<^term>‹tvars_ty τ›.› lemma tvars_subst_ty: "tvars_ty (subst_ty σ τ) = ⋃(tvars_ty ` σ ` tvars_ty τ)" by (induction τ) auto lemma subst_ty_id: "(⋀v. v ∈ tvars_ty τ ⟹ σ v = TVar v) ⟹ subst_ty σ τ = τ" by (induction τ) (auto intro: map_idI) lemma subst_ty_agree: "(⋀v. v ∈ tvars_ty τ ⟹ σ⇩1 v = σ⇩2 v) ⟹ subst_ty σ⇩1 τ = subst_ty σ⇩2 τ" by (induction τ) auto lemma subst_ty_compose: "subst_ty σ⇩1 (subst_ty σ⇩2 τ) = subst_ty (λv. subst_ty σ⇩1 (σ⇩2 v)) τ" by (induction τ) auto subsection ‹Contexts› text ‹A context is a finite partial function from variable names to types.› type_synonym ctx = "string ⇀ ty" text ‹Type variables of a context.› definition tvars_ctx :: "ctx ⇒ string set" where "tvars_ctx Γ = ⋃(tvars_ty ` ran Γ)" text ‹Applying a type substitution to a context.› definition subst_ctx :: "(string ⇒ ty) ⇒ ctx ⇒ ctx" where "subst_ctx σ Γ = map_option (subst_ty σ) ∘ Γ" lemma subst_ctx_dom [simp]: "dom (subst_ctx σ Γ) = dom Γ" by (auto simp: subst_ctx_def dom_def) lemma subst_ctx_app: "x ∈ dom Γ ⟹ subst_ctx σ Γ x = Some (subst_ty σ (the (Γ x)))" by (auto simp: subst_ctx_def dom_def) lemma subst_ctx_update: "subst_ctx σ (Γ(x ↦ τ)) = (subst_ctx σ Γ)(x ↦ subst_ty σ τ)" by (auto simp: subst_ctx_def) lemma subst_ctx_id: "(⋀v. v ∈ tvars_ctx Γ ⟹ σ v = TVar v) ⟹ subst_ctx σ Γ = Γ" using ranI by (fastforce intro!: map_option_idI subst_ty_id simp: subst_ctx_def tvars_ctx_def) subsection ‹Terms› subsubsection ‹Raw Terms› text ‹Raw terms include type constraints and binder constraints as annotations.›