-
Notifications
You must be signed in to change notification settings - Fork 225
Delta Cheatsheet
This document aims to be a complete reference for when definitions do and do not get unfolded in Lean. It will take several weeks until it even begins to resemble such a document.
-
A definition can be unfolded eagerly during
is_def_eq.Example:
is_def_eq(a, b)could in principle unfold all[reducible]layers of bothaandbeagerly before proceeding. This is not currently done. -
A definition can be unfolded lazily during
is_def_eq.Example: if
g := f, thenis_def_eq(f a, g a)could detect that the depth ofgis larger than the depth offand so unfoldgfirst before proceeding. -
A definition can be unfolded because a Pi type or a Sort is expected or required.
-
A definition can be unfolded if it matches a particular pattern.
Example: we might have reflexivity-simplification rules for definitions that wrap recursors that only trigger if it is known which pattern in the definition matches.
-
A definition can be unfolded because of a unification hint.
Example: In
is_def_eq(f, g), it might be the case that neitherfnorgwould normally be unfolded but that the pair(f, g)triggers a unification hint that causes one or both of them to be unfolded. -
A definition can be unfolded during normalization if it is fully applied.
Example:
composehas the[unfold_full]tag, and is unfolded during normalization if it is applied to all 3 arguments (i.e.compose f g xnormalizes tof (g x)). Note that the number of arguments is not well defined in general and depends on the delta/normalization strategy being used. Also note that we can simulate this behaviour easily with a single reflexivity-simplification rule. -
A definition can be unfolded during normalization if a specified argument is a constructor.
Example:
pred : nat -> nathas the[unfold 1]tag and gets unfolded during normalization if its argument is zero or succ. -
A definition can be unfolded during normalization if it is if an outer application is expecting a constructor at that position.
Example:
pairhas the[constructor]tag and so gets unfolded during normalization if an application ofpairoccurs in the major premise ofpair.rec. -
A definition can be unfolded eagerly and permanently by blast.
Example: blast currently unfolds every
[reducible]definition appearing in the context during initialization. Most blast modules that track lemmas in the environment (e.g. the simplifier) also unfold[reducible]definitions eagerly in the lemmas that they track. -
A definition can be unfolded "monotonically" by blast.
Example: given
H : f xandf x := g x x, blast might add the hypothesesH' : g x x := HandHH' : H = H' := rfl. We call this monotonic because we have not lost the original folded version. Note that we can use reflexivity-simplification rules monotonically as well.
-
Some data structures may be indexed by constant names or head symbols, and are hence inherently not robust to delta reduction.
Example: if
f := gbutfis not eagerly reduced by blast, then a[backward]lemmaHwith resultgwould not be considered for a backwards action for goalfeven ifis_def_eq(f, g). Note thatHwould not be tried even iffwere monotonically unfolded so that the context containedHfg : f = g. However,Hwould fire if e.g. asubstaction replaced the goal withg.
-
Sometimes we may expect
is_def_eqto fail and want to prevent a lot of wasted unfolding.Example: if we are doing search
-
Sometimes the user may say "I am willing to suffer a long delay if it turns out I am wrong about `is_def_eq(_, _) being true"
Example:
exacttactic -
Sometimes we know something is going to work, but we don't know what.
Example: even though we know something is going to work, the
assumptiontactic might still not want to unfold aggressively inH1 : P (fact 100), H2 : P 0 |- P 0, or else risk wasting time computingfact 100. I thinkassumptionshould be probably conservative and the user should useexactif reductions are needed, orblastif the hypothesis in question contains system-generated names.