Additional operations on expr and related types #
This file defines basic operations on the types expr, name, declaration, level, environment.
This file is mostly for non-tactics. Tactics should generally be placed in tactic.core
.
Tags #
expr, name, declaration, level, environment, meta, metaprogramming, tactic
Declarations about binder_info
#
Equations
The brackets corresponding to a given binder_info.
Equations
- binder_info.aux_decl.brackets = ("(", ")")
- binder_info.inst_implicit.brackets = ("[", "]")
- binder_info.strict_implicit.brackets = ("{{", "}}")
- binder_info.implicit.brackets = ("{", "}")
- binder_info.default.brackets = ("(", ")")
Find the largest prefix n
of a name
such that f n ≠ none
, then replace this prefix
with the value of f n
.
Equations
- name.map_prefix f (name.mk_numeral d n') = (f (name.mk_numeral d n')).get_or_else (name.mk_numeral d (name.map_prefix f n'))
- name.map_prefix f (name.mk_string s n') = (f (name.mk_string s n')).get_or_else (name.mk_string s (name.map_prefix f n'))
- name.map_prefix f name.anonymous = name.anonymous
Build a name from components. For example from_components ["foo","bar"]
becomes
`foo.bar
Equations
- name.from_components = from_components_aux name.anonymous
Append a string to the last component of a name.
Equations
- (name.mk_numeral ᾰ ᾰ_1).append_suffix _x = name.mk_numeral ᾰ ᾰ_1
- (name.mk_string s n).append_suffix s' = name.mk_string (s ++ s') n
- name.anonymous.append_suffix _x = name.anonymous
Update the last component of a name.
Equations
- name.update_last f (name.mk_numeral ᾰ ᾰ_1) = name.mk_numeral ᾰ ᾰ_1
- name.update_last f (name.mk_string s n) = name.mk_string (f s) n
- name.update_last f name.anonymous = name.anonymous
append_to_last nm s is_prefix
adds s
to the last component of nm
,
either as prefix or as suffix (specified by is_prefix
), separated by _
.
Used by simps_add_projections
.
Equations
- nm.append_to_last s is_prefix = name.update_last (λ (s' : string), ite ↥is_prefix (s ++ "_" ++ s') (s' ++ "_" ++ s)) nm
Checks whether nm
has a prefix (including itself) such that P is true
Equations
- name.has_prefix P (name.mk_numeral s nm) = decidable.to_bool (↥(P (name.mk_numeral s nm)) ∨ ↥(name.has_prefix P nm))
- name.has_prefix P (name.mk_string s nm) = decidable.to_bool (↥(P (name.mk_string s nm)) ∨ ↥(name.has_prefix P nm))
- name.has_prefix P name.anonymous = bool.ff
last_string n
returns the rightmost component of n
, ignoring numeral components.
For example, last_string `a.b.c.33
will return `c
.
Equations
- (name.mk_numeral _x n).last_string = n.last_string
- (name.mk_string s _x).last_string = s
- name.anonymous.last_string = "[anonymous]"
In surface Lean, we can write anonymous Π binders (i.e. binders where the argument is not named) using the function arrow notation:
inductive test : Type
| intro : unit → test
After elaboration, however, every binder must have a name, so Lean generates
one. In the example, the binder in the type of intro
is anonymous, so Lean
gives it the name ᾰ
:
test.intro : ∀ (ᾰ : unit), test
When there are multiple anonymous binders, they are named ᾰ_1
, ᾰ_2
etc.
Thus, when we want to know whether the user named a binder, we can check whether the name follows this scheme. Note, however, that this is not reliable. When the user writes (for whatever reason)
inductive test : Type
| intro : ∀ (ᾰ : unit), test
we cannot tell that the binder was, in fact, named.
The function name.is_likely_generated_binder_name
checks if
a name is of the form ᾰ
, ᾰ_1
, etc.
Converting between expressions and numerals #
There are a number of ways to convert between expressions and numerals, depending on the input and output types and whether you want to infer the necessary type classes.
See also the tactics expr.of_nat
, expr.of_int
, expr.of_rat
.
Some declarations work with open expressions, i.e. an expr that has free variables.
Terms will free variables are not well-typed, and one should not use them in tactics like
infer_type
or unify
. You can still do syntactic analysis/manipulation on them.
The reason for working with open types is for performance: instantiating variables requires
iterating through the expression. In one performance test pi_binders
was more than 6x
quicker than mk_local_pis
(when applied to the type of all imported declarations 100x).
Declarations about environment
#
is_eta_expansion
#
In this section we define the tactic is_eta_expansion
which checks whether an expression
is an eta-expansion of a structure. (not to be confused with eta-expanion for λ
).