Case tags #
Case tags are an internal mechanism used by certain tactics to communicate with
each other. They are generated by the tactics cases
, induction
and
with_cases
('cases-like tactics'), which generate goals corresponding to the
'cases' of an inductive hypothesis. Each of these goals carries a case tag. They
are consumed by the case
tactic, which focuses on one of these cases. Their
purpose is twofold:
- Give intuitive names to case goals. For example, when performing induction on
a natural number, two cases are generated: one tagged with
nat.zero
and one tagged withnat.succ
. Users can then focus on e.g. the second goal withcase succ {...}
. - Communicate which new hypotheses were introduced by the cases-like tactic
that generated the goal. For example, when performing induction on a
list α
, thecons
case introduces two hypotheses corresponding to the two arguments of thecons
constructor.case
allows users to name these withcase cons : x xs {...}
. To perform this renaming,case
needs to know which hypotheses to rename; this information is contained in the case tag for thecons
goal.
Module contents #
This module defines
- what a case tag is (see
case_tag
); - how to render a
case_tag
as a list of names (seerender
); - how to parse a
case_tag
from a list of names (seeparse
); - how to match a
case_tag
with a sequence of names given by the user (seematch_tag
).
- pi : list name → ℕ → tactic.interactive.case_tag
- hyps : list name → list name → tactic.interactive.case_tag
A case tag carries the following information:
-
A list of names identifying the case ('case names'). This is usually a list of constructor names, one for each case split that was performed. For example, the sequence of tactics
cases n; cases xs
, wheren
is a natural number andxs
is a list, will generate four cases tagged as follows:Note: In the case tag, the case names are stored in reverse order. Thus, the case names of the first case tag would be
list.nil, nat.zero
. This is because when printing a goal tag (as part of a goal state), Lean prints all non-internal names in reverse order. -
Information about the arguments introduced by the cases-like tactic. Different tactics work slightly different in this regard:
-
The
with_cases
tactic generates goals where the target quantifies over any added hypotheses. For example,with_cases { cases xs }
, wherexs
is alist α
, will generate a target of the formα → list α → ...
in thecons
case, where the two arguments correspond to the two arguments of thecons
constructor. Goals of this form are tagged with api
case tag (since the target is a pi type). In addition to the case names, it contains a natural number,num_arguments
, which specifies how many of the arguments that the target quantifies over were introduced bywith_cases
.For example, given
n : ℕ
andxs : list α
, the fourth goal generated bywith_cases { cases n; induction xs }
has this form:... ⊢ ℕ → α → ∀ (xs' : list α), P xs' → ...
The corresponding case tag is
since the first four arguments of the target were introduced by
with_cases {...}
. -
The
cases
andinduction
tactics do not add arguments to the target, but rather introduce them as hypotheses in the local context. Goals of this form are tagged with ahyps
case tag. In addition to the case names, it contains a list of unique names of the hypotheses that were introduced.For example, given
xs : list α
, the second goal generated byinduction xs
has this form:... x : α xs' : list α ih_xs' : P xs' ⊢ ...
The corresponding goal tag is
hyps [`list.cons] [`<x>, `<xs'>, `<ih_xs'>]
where ````
``` denotes the unique name of a hypothesis h
.Note: Many tactics do not preserve the unique names of hypotheses (particularly those tactics that use
revert
). Therefore, ahyps
case tag is only guaranteed to be valid directly after it was generated.
-
- exact_match : tactic.interactive.case_tag.match_result
- fuzzy_match : tactic.interactive.case_tag.match_result
- no_match : tactic.interactive.case_tag.match_result
Indicates the result of matching a list of names against the names of a case
tag. See match_tag
.
The 'minimum' of two match results:
- If any of the arguments is
no_match
, the result isno_match
. - Otherwise, if any of the arguments is
fuzzy_match
, the result isfuzzy_match
. - Otherwise (iff both arguments are
exact_match
), the result isexact_match
.
Equations
- tactic.interactive.case_tag.match_result.no_match.combine _x = tactic.interactive.case_tag.match_result.no_match
- tactic.interactive.case_tag.match_result.fuzzy_match.combine tactic.interactive.case_tag.match_result.no_match = tactic.interactive.case_tag.match_result.no_match
- tactic.interactive.case_tag.match_result.fuzzy_match.combine tactic.interactive.case_tag.match_result.fuzzy_match = tactic.interactive.case_tag.match_result.fuzzy_match
- tactic.interactive.case_tag.match_result.fuzzy_match.combine tactic.interactive.case_tag.match_result.exact_match = tactic.interactive.case_tag.match_result.fuzzy_match
- tactic.interactive.case_tag.match_result.exact_match.combine tactic.interactive.case_tag.match_result.no_match = tactic.interactive.case_tag.match_result.no_match
- tactic.interactive.case_tag.match_result.exact_match.combine tactic.interactive.case_tag.match_result.fuzzy_match = tactic.interactive.case_tag.match_result.fuzzy_match
- tactic.interactive.case_tag.match_result.exact_match.combine tactic.interactive.case_tag.match_result.exact_match = tactic.interactive.case_tag.match_result.exact_match