I've noticed that the process of coding a definition in Agda that is universe polymorphic usually requires little thought in how the Level
parameters are specified. Most of the time in the input you can just use a different Level
term for each place where it's applicable, and in the the output use the ⊔
and occasionally the lsuc
of all previous Level
terms if it's needed.
This often results in the universe polymorphic versions of definitions having boilerplate code tacked on, such as in the following example with the definition of dependent pair types.
open import Agda.Primitive public
-- Non-universe polymorphic example
data Σ (A : Set)(B : A → Set) : Set where
pair : (x : A) → B x → Σ A B
-- Universe polymorphic example
data Σ' {i j : Level}(A : Set i)(B : A → Set j) : Set (i ⊔ j) where
pair : (x : A) → B x → Σ' A B
Why is it not the case that whenever we write Set
, Agda implicitly handles the universe polymorphism for us so we don't have to manually specify these Level
terms? What benefits does this provide?