Theory Examples
section ‹Basic Eisbach examples›
theory Examples
imports Main Eisbach_Tools
begin
subsection ‹Basic methods›
method my_intros = (rule conjI | rule impI)
lemma "P ∧ Q ⟶ Z ∧ X"
apply my_intros+
oops
method my_intros' uses intros = (rule conjI | rule impI | rule intros)
lemma "P ∧ Q ⟶ Z ∨ X"
apply (my_intros' intros: disjI1)+
oops
method my_spec for x :: 'a = (drule spec[where x="x"])
lemma "∀x. P x ⟹ P x"
apply (my_spec x)
apply assumption
done
subsection ‹Focusing and matching›
method match_test =
(match premises in U: "P x ∧ Q x" for P Q x ⇒
‹print_term P,
print_term Q,
print_term x,
print_fact U›)
lemma "⋀x. P x ∧ Q x ⟹ A x ∧ B x ⟹ R x y ⟹ True"
apply match_test
back
back
back
back
back
back
back
back
back
oops
text ‹Use matching to avoid "improper" methods›
lemma focus_test:
shows "⋀x. ∀x. P x ⟹ P x"
apply (my_spec "x :: 'a", assumption)?
apply (match conclusion in "P x" for x ⇒ ‹my_spec x, assumption›)
done
text ‹Matches are exclusive. Backtracking will not occur past a match›
method match_test' =
(match conclusion in
"P ∧ Q" for P Q ⇒
‹print_term P, print_term Q, rule conjI[where P="P" and Q="Q"]; assumption›
¦ "H" for H ⇒ ‹print_term H›)
text ‹Solves goal›
lemma "P ⟹ Q ⟹ P ∧ Q"
apply match_test'
done
text ‹Fall-through case never taken›
lemma "P ∧ Q"
apply match_test'?
oops
lemma "P"
apply match_test'
oops
method my_spec_guess =
(match conclusion in "P (x :: 'a)" for P x ⇒
‹drule spec[where x=x],
print_term P,
print_term x›)
lemma "∀x. P (x :: nat) ⟹ Q (x :: nat)"
apply my_spec_guess
oops
method my_spec_guess2 =
(match premises in U[thin]:"∀x. P x ⟶ Q x" and U':"P x" for P Q x ⇒
‹insert spec[where x=x, OF U],
print_term P,
print_term Q›)
lemma "∀x. P x ⟶ Q x ⟹ Q x ⟹ Q x"
apply my_spec_guess2?
oops
lemma "∀x. P x ⟶ Q x ⟹ P x ⟹ Q x"
apply my_spec_guess2
apply (erule mp)
apply assumption
done
subsection ‹Higher-order methods›
method higher_order_example for x methods meth =
(cases x, meth, meth)
lemma
assumes A: "x = Some a"
shows "the x = a"
by (higher_order_example x ‹simp add: A›)
subsection ‹Recursion›
method recursion_example for x :: bool =
(print_term x,
match (x) in "A ∧ B" for A B ⇒
‹print_term A,
print_term B,
recursion_example A,
recursion_example B | -›)
lemma "P"
apply (recursion_example "(A ∧ D) ∧ (B ∧ C)")
oops
subsection ‹Solves combinator›
lemma "A ⟹ B ⟹ A ∧ B"
apply (solves ‹rule conjI›)?
apply (solves ‹rule conjI, assumption, assumption›)
done
subsection ‹Demo›
named_theorems intros and elims and subst
method prop_solver declares intros elims subst =
(assumption |
rule intros | erule elims |
subst subst | subst (asm) subst |
(erule notE; solves prop_solver))+
lemmas [intros] =
conjI
impI
disjCI
iffI
notI
lemmas [elims] =
impCE
conjE
disjE
lemma "((A ∨ B) ∧ (A ⟶ C) ∧ (B ⟶ C)) ⟶ C"
apply prop_solver
done
method guess_all =
(match premises in U[thin]:"∀x. P (x :: 'a)" for P ⇒
‹match premises in "?H (y :: 'a)" for y ⇒
‹rule allE[where P = P and x = y, OF U]›
| match conclusion in "?H (y :: 'a)" for y ⇒
‹rule allE[where P = P and x = y, OF U]››)
lemma "(∀x. P x ⟶ Q x) ⟹ P y ⟹ Q y"
apply guess_all
apply prop_solver
done
lemma "(∀x. P x ⟶ Q x) ⟹ P z ⟹ P y ⟹ Q y"
apply (solves ‹guess_all, prop_solver›)
done
method guess_ex =
(match conclusion in
"∃x. P (x :: 'a)" for P ⇒
‹match premises in "?H (x :: 'a)" for x ⇒
‹rule exI[where x=x]››)
lemma "P x ⟹ ∃x. P x"
apply guess_ex
apply prop_solver
done
method fol_solver =
((guess_ex | guess_all | prop_solver); solves fol_solver)
declare
allI [intros]
exE [elims]
ex_simps [subst]
all_simps [subst]
lemma "(∀x. P x) ∧ (∀x. Q x) ⟹ (∀x. P x ∧ Q x)"
and "∃x. P x ⟶ (∀x. P x)"
and "(∃x. ∀y. R x y) ⟶ (∀y. ∃x. R x y)"
by fol_solver+
text ‹
Eisbach_Tools provides the catch method, which catches run-time method
errors. In this example the OF attribute throws an error when it can't
compose H with A, forcing H to be re-bound to different members of imps
until it succeeds.
›
lemma
assumes imps: "A ⟹ B" "A ⟹ C" "B ⟹ D"
assumes A: "A"
shows "B ∧ C"
apply (rule conjI)
apply ((match imps in H:"_ ⟹ _" ⇒ ‹catch ‹rule H[OF A], print_fact H› ‹print_fact H, fail››)+)
done
text ‹
Eisbach_Tools provides the curry and uncurry attributes. This is useful
when the number of premises of a thm isn't known statically. The pattern
\<^term>‹P ⟹ Q› matches P against the major premise of a thm, and Q is the
rest of the premises with the conclusion. If we first uncurry, then \<^term>‹P ⟹ Q› will match P with the conjunction of all the premises, and Q with
the final conclusion of the rule.
›
lemma
assumes imps: "A ⟹ B ⟹ C" "D ⟹ C" "E ⟹ D ⟹ A"
shows "(A ⟶ B ⟶ C) ∧ (D ⟶ C)"
by (match imps[uncurry] in H[curry]:"_ ⟹ C" (cut, multi) ⇒
‹match H in "E ⟹ _" ⇒ fail
¦ _ ⇒ ‹simp add: H››)
end