-
Notifications
You must be signed in to change notification settings - Fork 766
Description
The following shows the current way that many common variations on pi types are pretty printed:
variable (α : Nat → Type) (p q : Prop) (P : Nat → Prop)
#check (i : Nat) → Nat -- Nat → Nat
#check {i : Nat} → Nat -- {i : Nat} → Nat
#check (h : p) → q -- p → q
#check (i : Nat) → p -- Nat → p
#check (i : Nat) → α i -- (i : Nat) → α i
#check {i : Nat} → α i -- {i : Nat} → α i
#check (i : Nat) → P i -- ∀ (i : Nat), P i
#check {i : Nat} → P i -- ∀ {i : Nat}, P i
#check {i : Nat} → p -- ∀ {i : Nat}, pThis RFC is primarily about the Nat → p case, which tends to be the most surprising (it is a source of questions on Zulip). This sort of Prop-valued pi type frequently appears in the course of rewrites, where a forall quantifier becomes non-dependent:
example (P : Nat → Prop) (q : Prop) (h : ∀ n, P n = q) (hq : q) :
∀ n, P n :=
by
simp [h]
-- ⊢ Nat → q
exact λ _ => hqThe meaning of a non-dependent pi from a Type to a Prop is generally a universal quantification, so the pretty printer should represent such pi types in some way such that this is clear.
Concretely, given ι : Sort u and α : ι → Sort v, then when u > 0 and v = 0 we should make sure to use ∀ when pretty printing the corresponding pi type for α, even if the pi type is nondependent.
The nondependent u = 0 and v = 0 case should be left alone since the implication arrow serves its purpose just fine.
There are a couple of additional considerations presentation-wise.
While pretty printing pi types using ∀ gives the user the information that it is Prop-valued, this leads to the user not being able to immediately see whether the quantifier is dependent or not; in discussion, it was brought up that this information is important for expert Lean users. One possible solution to this is to pretty print Nat → p as ∀ (_ : Nat), p (rather than ∀ (i : Nat), p) with a placeholder for the variable. This way one can immediately see it is a Prop-valued non-implication non-dependent pi type.
This leads to some inconsistency when it comes to non-default binders for other nondependent pi types. One might entertain using placeholders in every context where a non-dependent pi would print a binder. For example, {_ : Nat} → Nat rather than {i : Nat} → Nat. This does lead to loss of information that is important for (i := 22) argument notation. There are other solutions (such as using a tombstone, or using semantic coloring in an editor), or we can simply choose to tolerate any potential inconsistency here.
In a similar direction, for instance binders we currently have
#check (α : Type) → [DecidableEq α] → True
-- ∀ (α : Type) [inst : DecidableEq α], TrueWith suggestions above, this would pretty print as ∀ (α : Type) [_ : DecidableEq α], True since the instance binder is non-dependent, but one may as well pretty print it as ∀ (α : Type) [DecidableEq α], True since it gives the same amount of information while looking prettier.
(The Lean 3 version of this RFC is lean PR 770.)