/- Isabelle style tactics. This test is based on a file created by Gabriel Ebner. -/ import data.lazy_list universe variables u meta def lazy_tactic (α : Type u) := tactic_state → lazy_list (α × tactic_state) namespace lazy_tactic open lazy_list meta def of_tactic {α : Type u} (t : tactic α) : lazy_tactic α := λ s, match t s with | result.success a new_s := lazy_list.singleton (a, new_s) | result.exception f e s := lazy_list.nil end meta instance {α : Type} : has_coe (tactic α) (lazy_tactic α) := ⟨of_tactic⟩ protected meta def return {α} (a : α) : lazy_tactic α := λ s, lazy_list.singleton (a, s) protected meta def bind {α β} : lazy_tactic α → (α → lazy_tactic β) → lazy_tactic β := λ t₁ t₂ s, join (for (t₁ s) (λ ⟨a, new_s⟩, t₂ a new_s)) protected meta def orelse {α} (t₁ t₂ : lazy_tactic α) : lazy_tactic α := λ s, append (t₁ s) (t₂ s) protected meta def failure {α} : lazy_tactic α := λ s, nil meta instance : monad lazy_tactic := { pure := @lazy_tactic.return, bind := @lazy_tactic.bind } meta instance : alternative lazy_tactic := { lazy_tactic.monad with failure := @lazy_tactic.failure, orelse := @lazy_tactic.orelse } meta def choose {α} (xs : list α) : lazy_tactic α := λ s, of_list $ xs^.for (λ a, (a, s)) meta def run {α} (t : lazy_tactic α) : tactic α := λ s, match t s with | nil := tactic.failed s | cons (a, new_s) ss := result.success a new_s end open tactic private meta def try_constructors : list name → lazy_tactic unit | [] := failure | (c::cs) := (mk_const c >>= apply : tactic unit) <|> try_constructors cs /- Backtracking version of constructor -/ meta def constructor : lazy_tactic unit := do t ← target, cs ← get_constructors_for t, try_constructors cs end lazy_tactic open lazy_tactic example (p q : Prop) : q → p ∨ q := by run $ do tactic.intros, constructor, tactic.trace_state, tactic.assumption meta def naive_instantiation : lazy_tactic unit := let vals := [`(1),`(2),`(3)] in do x ← choose vals, y ← choose vals, e ← tactic.to_expr `(nat.add_comm %%x %%y), tactic.trace e, tactic.exact e lemma ex : 1 + 3 = 3 + 1 := by naive_instantiation^.run