Recursive cases (rcases) tactic and related tactics #
rcases is a tactic that will perform cases recursively, according to a pattern. It is used to
destructure hypotheses or expressions composed of inductive types like h1 : a ∧ b ∧ c ∨ d or
h2 : ∃ x y, trans_rel R x y. Usual usage might be rcases h1 with ⟨ha, hb, hc⟩ | hd or
rcases h2 with ⟨x, y, _ | ⟨z, hxz, hzy⟩⟩ for these examples.
Each element of an rcases pattern is matched against a particular local hypothesis (most of which
are generated during the execution of rcases and represent individual elements destructured from
the input expression). An rcases pattern has the following grammar:
- A name like x, which names the active hypothesis asx.
- A blank _, which does nothing (letting the automatic naming system used bycasesname the hypothesis).
- A hyphen -, which clears the active hypothesis and any dependents.
- The keyword rfl, which expects the hypothesis to beh : a = b, and callssubston the hypothesis (which has the effect of replacingbwithaeverywhere or vice versa).
- A type ascription p : ty, which sets the type of the hypothesis totyand then matches it againstp. (Of course,tymust unify with the actual type ofhfor this to work.)
- A tuple pattern ⟨p1, p2, p3⟩, which matches a constructor with many arguments, or a series of nested conjunctions or existentials. For example if the active hypothesis isa ∧ b ∧ c, then the conjunction will be destructured, andp1will be matched againsta,p2againstband so on.
- An alteration pattern p1 | p2 | p3, which matches an inductive type with multiple constructors, or a nested disjunction likea ∨ b ∨ c.
The patterns are fairly liberal about the exact shape of the constructors, and will insert additional alternation branches and tuple arguments if there are not enough arguments provided, and reuse the tail for further matches if there are too many arguments provided to alternation and tuple patterns.
This file also contains the obtain and rintro tactics, which use the same syntax of rcases
patterns but with a slightly different use case:
- rintro(or- rintros) is used like- rintro x ⟨y, z⟩and is the same as- introsfollowed by- rcaseson the newly introduced arguments.
- obtainis the same as- rcasesbut with a syntax styled after- haverather than- cases.- obtain ⟨hx, hy⟩ | hz := foois equivalent to- rcases foo with ⟨hx, hy⟩ | hz. Unlike- rcases,- obtainalso allows one to omit- := foo, although a type must be provided in this case, as in- obtain ⟨hx, hy⟩ | hz : a ∧ b ∨ c, in which case it produces a subgoal for proving- a ∧ b ∨ cin addition to the subgoals- hx : a, hy : b |- goaland- hz : c |- goal.
Tags #
rcases, rintro, obtain, destructuring, cases, pattern matching, match
These synonyms for list are used to clarify the meanings of the many
usages of lists in this module.
- 
listΣis used where a list represents a disjunction, such as the list of possible constructors of an inductive type.
- 
listΠis used where a list represents a conjunction, such as the list of arguments of an individual constructor.
These are merely type synonyms, and so are not checked for consistency by the compiler.
The def/local notation combination makes Lean retain these
annotations in reported types.
A list, with a disjunctive meaning (like a list of inductive constructors, or subgoals)
Equations
A list, with a conjunctive meaning (like a list of constructor arguments, or hypotheses)
Equations
Like zip_with, but if the lists don't match in length, the excess elements will be put at the
end of the result.
Equations
- tactic.merge_list m (a :: l₁) (b :: l₂) = m a b :: tactic.merge_list m l₁ l₂
- tactic.merge_list m (hd :: tl) list.nil = hd :: tl
- tactic.merge_list m list.nil (hd :: tl) = hd :: tl
- tactic.merge_list m list.nil list.nil = list.nil
rcases is a tactic that will perform cases recursively, according to a pattern. It is used to
destructure hypotheses or expressions composed of inductive types like h1 : a ∧ b ∧ c ∨ d or
h2 : ∃ x y, trans_rel R x y. Usual usage might be rcases h1 with ⟨ha, hb, hc⟩ | hd or
rcases h2 with ⟨x, y, _ | ⟨z, hxz, hzy⟩⟩ for these examples.
Each element of an rcases pattern is matched against a particular local hypothesis (most of which
are generated during the execution of rcases and represent individual elements destructured from
the input expression). An rcases pattern has the following grammar:
- A name like x, which names the active hypothesis asx.
- A blank _, which does nothing (letting the automatic naming system used bycasesname the hypothesis).
- A hyphen -, which clears the active hypothesis and any dependents.
- The keyword rfl, which expects the hypothesis to beh : a = b, and callssubston the hypothesis (which has the effect of replacingbwithaeverywhere or vice versa).
- A type ascription p : ty, which sets the type of the hypothesis totyand then matches it againstp. (Of course,tymust unify with the actual type ofhfor this to work.)
- A tuple pattern ⟨p1, p2, p3⟩, which matches a constructor with many arguments, or a series of nested conjunctions or existentials. For example if the active hypothesis isa ∧ b ∧ c, then the conjunction will be destructured, andp1will be matched againsta,p2againstband so on.
- An alteration pattern p1 | p2 | p3, which matches an inductive type with multiple constructors, or a nested disjunction likea ∨ b ∨ c.
A pattern like ⟨a, b, c⟩ | ⟨d, e⟩ will do a split over the inductive datatype,
naming the first three parameters of the first constructor as a,b,c and the
first two of the second constructor d,e. If the list is not as long as the
number of arguments to the constructor or the number of constructors, the
remaining variables will be automatically named. If there are nested brackets
such as ⟨⟨a⟩, b | c⟩ | d then these will cause more case splits as necessary.
If there are too many arguments, such as ⟨a, b, c⟩ for splitting on
∃ x, ∃ y, p x, then it will be treated as ⟨a, ⟨b, c⟩⟩, splitting the last
parameter as necessary.
rcases also has special support for quotient types: quotient induction into Prop works like
matching on the constructor quot.mk.
rcases h : e with PAT will do the same as rcases e with PAT with the exception that an
assumption h : e = PAT will be added to the context.
rcases? e will perform case splits on e in the same way as rcases e,
but rather than accepting a pattern, it does a maximal cases and prints the
pattern that would produce this case splitting. The default maximum depth is 5,
but this can be modified with rcases? e : n.
The rintro tactic is a combination of the intros tactic with rcases to
allow for destructuring patterns while introducing variables. See rcases for
a description of supported patterns. For example, rintro (a | ⟨b, c⟩) ⟨d, e⟩
will introduce two variables, and then do case splits on both of them producing
two subgoals, one with variables a d e and the other with b c d e.
rintro, unlike rcases, also supports the form (x y : ty) for introducing
and type-ascripting multiple variables at once, similar to binders.
rintro? will introduce and case split on variables in the same way as
rintro, but will also print the rintro invocation that would have the same
result. Like rcases?, rintro? : n allows for modifying the
depth of splitting; the default is 5.
rintros is an alias for rintro.
The obtain tactic is a combination of have and rcases. See rcases for
a description of supported patterns.
obtain ⟨patt⟩ : type,
{ ... }
is equivalent to
have h : type,
{ ... },
rcases h with ⟨patt⟩
The syntax obtain ⟨patt⟩ : type := proof is also supported.
If ⟨patt⟩ is omitted, rcases will try to infer the pattern.
If type is omitted, := proof is required.
The rsuffices tactic is an alternative version of suffices, that allows the usage
of any syntax that would be valid in an obtain block. This tactic just calls obtain
on the expression, and then rotate 1.
The rsufficesI tactic is an instance-cache aware version of rsuffices; it resets the instance
cache on the resulting goals.