Arrow α β is definitionally equal to α → β, but represented as a function
application rather than Expr.forallE.
This representation is useful for proof automation that builds nested implications
like pₙ → ... → p₂ → p₁. With Expr.forallE, each nesting level introduces a
binder that bumps de Bruijn indices in subterms, destroying sharing even with
hash-consing. For example, if p₁ contains #20, then at depth 2 it becomes #21,
at depth 3 it becomes #22, etc., causing quadratic proof growth.
With arrow, both arguments are explicit (not under binders), so subterms remain
identical across nesting levels and can be shared, yielding linear-sized proofs.
Equations
- Lean.Arrow α β = (α → β)
Instances For
Congruence lemmas for have have kernel performance issues when stated using have directly.
Illustration of the problem: the kernel infers that the type of
have_congr (fun x => b) (fun x => b') h₁ h₂
is
(have x := a; (fun x => b) x) = (have x := a'; (fun x => b') x)
rather than
(have x := a; b x) = (have x := a'; b' x)
That means the kernel will do whnf_core at every step of checking a sequence of these lemmas.
Thus, we get quadratically many zeta reductions.
For reference, we have the have versions of the theorems in the following comment,
and then after that we have the versions that simpHaveTelescope actually uses,
which avoid this issue.