-
Notifications
You must be signed in to change notification settings - Fork 299
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(tactic/fin_cases): a tactic to case bash on
fin n
(#352)
* feat(tactic/fin_cases): a tactic to case bash on `fin n` * using core is_numeral * removing guard just rely on eval_expr to decide if we have an explicit nat * add parsing, tests, documentation * don't fail if the rewrite fails * fixes
- Loading branch information
1 parent
e585bed
commit 90982d7
Showing
4 changed files
with
85 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/- | ||
Copyright (c) 2018 Scott Morrison. All rights reserved. | ||
Released under Apache 2.0 license as described in the file LICENSE. | ||
Author: Scott Morrison | ||
Case bashing on `fin n`, for explicit numerals `n`. | ||
-/ | ||
import data.fin | ||
|
||
namespace tactic | ||
open lean.parser | ||
open interactive interactive.types expr | ||
|
||
meta def fin_cases_at (e : expr) : tactic unit := | ||
do `(fin %%n) ← infer_type e, | ||
n ← eval_expr ℕ n, | ||
[(_, [val, bd], _)] ← cases_core e [`val, `bd], | ||
-- We now call `cases val` n times, rotating the generated goals out of the way. | ||
iterate_at_most n (do val ← get_local `val, cases val, rotate 1), | ||
-- We've got an absurd hypothesis `bd`, but it is messy: it looks like | ||
-- `nat.succ (... (nat.succ val)) < n` | ||
-- So we rewrite it as `bd : val + 1 + ... + 1 < n`, and use `dec_trivial` to kill it. | ||
ss ← mk_const `nat.succ_eq_add_one, | ||
bd ← get_local `bd, | ||
(list.range n).mfoldl (λ bd _, do rewrite_hyp ss bd) bd, | ||
to_expr ``(absurd %%bd dec_trivial) >>= exact, | ||
-- We put the goals back in order, and clear the `bd` hypotheses. | ||
iterate_exactly n (do rotate_right 1, | ||
try `[rw [fin.mk_val]], | ||
try (get_local `bd >>= clear)) | ||
|
||
namespace interactive | ||
private meta def hyp := tk "*" *> return none <|> some <$> ident | ||
|
||
/-- | ||
`fin_cases h` performs case analysis on a hypothesis `h : fin n`, where `n` is an explicit natural | ||
number. `fin_cases *` performs case analysis on all suitable hypotheses. | ||
As an example, in | ||
``` | ||
example (f : ℕ → Prop) (p : fin 3) (h0 : f 0) (h1 : f 1) (h2 : f 2) : f p.val := | ||
begin | ||
fin_cases p, | ||
all_goals { assumption } | ||
end | ||
``` | ||
after `fin_cases p`, there are three goals, `f 0`, `f 1`, and `f 2`. | ||
-/ | ||
meta def fin_cases : parse hyp → tactic unit | ||
| none := do ctx ← local_context, | ||
ctx.mfirst fin_cases_at <|> fail "No explicit `fin n` hypotheses." | ||
| (some n) := do h ← get_local n, fin_cases_at h | ||
end interactive | ||
|
||
end tactic |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import tactic.fin_cases | ||
|
||
|
||
example (f : ℕ → Prop) (p : fin 3) (h0 : f 0) (h1 : f 1) (h2 : f 2) : f p.val := | ||
begin | ||
fin_cases *, | ||
all_goals { assumption } | ||
end | ||
|
||
example (x2 : fin 2) (x3 : fin 3) (n : nat) (y : fin n) : x2.val * x3.val = x3.val * x2.val := | ||
begin | ||
fin_cases x2; | ||
fin_cases x3, | ||
success_if_fail { fin_cases * }, | ||
success_if_fail { fin_cases y }, | ||
all_goals { simp }, | ||
end |