In the standard library, we should use explicit universe variables for universe polymorphic definitions. Users that want to declare universe polymorphic definitions but do not want to provide universe level parameters should use Type _ or Type*
83 lines
3.3 KiB
Text
83 lines
3.3 KiB
Text
universe variables u v
|
|
inductive imf {A : Type u} {B : Type v} (f : A → B) : B → Type (max 1 u v)
|
|
| mk : ∀ (a : A), imf (f a)
|
|
|
|
definition inv_1 {A : Type u} {B : Type v} (f : A → B) : ∀ (b : B), imf f b → A
|
|
| .(f a) (imf.mk .f a) := a
|
|
|
|
definition inv_2 {A : Type u} {B : Type v} (f : A → B) : ∀ (b : B), imf f b → A
|
|
| ._ (imf.mk ._ a) := a
|
|
|
|
definition mk {A : Type u} {B : Type v} {f : A → B} (a : A) := imf.mk f a
|
|
|
|
definition inv_3 {A : Type u} {B : Type v} (f : A → B) : ∀ (b : B), imf f b → A
|
|
| .(f a) (mk a) := a -- Error, mk is not a constructor
|
|
|
|
definition inv_4 {A : Type u} {B : Type v} (f : A → B) : ∀ (b : B), imf f b → A
|
|
| .(f a) (.mk a) := a -- Error, we cannot use inaccessible annotation around functions in applications
|
|
|
|
attribute [pattern] mk
|
|
|
|
definition inv_5 {A : Type u} {B : Type v} (f : A → B) : ∀ (b : B), imf f b → A
|
|
| .(f a) (mk a) := a
|
|
|
|
definition inv_6 {A : Type u} {B : Type v} (f : A → B) : ∀ (b : B), imf f b → A
|
|
| (f a) (mk a) := a -- Error, 'a' is being "declared" twice in the pattern
|
|
|
|
definition inv_7 {A : Type u} {B : Type v} (f : A → B) : ∀ (b : B), imf f b → A
|
|
| (f a) (mk b) := a -- Typing error, it would also fail when compiling the pattern
|
|
|
|
definition g_1 : nat → nat → nat
|
|
| a a := a -- Error, 'a' is being "declared" twice
|
|
|
|
definition g_2 (a : nat) : nat → nat → nat
|
|
| a b := a
|
|
|
|
example (a b c : nat) : g_2 a b c = b :=
|
|
rfl
|
|
|
|
inductive vec1 (A : Type u) : nat → Type (max 1 u)
|
|
| nil : vec1 0
|
|
| cons : ∀ n, A → vec1 n → vec1 (n+1)
|
|
|
|
section
|
|
open vec1
|
|
|
|
definition map_1 {A : Type u} (f : A → A → A) : Π {n}, vec1 A n → vec1 A n → vec1 A n
|
|
| 0 (nil .A) (nil .A) := nil A
|
|
| (n+1) (cons .n h₁ v₁) (cons .n h₂ v₂) := cons n (f h₁ h₂) (map_1 v₁ v₂)
|
|
|
|
definition map_2 {A : Type u} (f : A → A → A) : Π {n}, vec1 A n → vec1 A n → vec1 A n
|
|
| 0 (nil ._) (nil ._) := nil A
|
|
| (n+1) (cons ._ h₁ v₁) (cons ._ h₂ v₂) := cons n (f h₁ h₂) (map_2 v₁ v₂)
|
|
|
|
/- In map_3, we use the inaccessible terms to avoid pattern/matching on the first argument -/
|
|
definition map_3 {A : Type u} (f : A → A → A) : Π {n}, vec1 A n → vec1 A n → vec1 A n
|
|
| ._ (nil ._) (nil ._) := nil A
|
|
| ._ (cons n h₁ v₁) (cons .n h₂ v₂) := cons n (f h₁ h₂) (map_3 v₁ v₂)
|
|
end
|
|
|
|
inductive vec2 (A : Type u) : nat → Type (max 1 u)
|
|
| nil {} : vec2 0
|
|
| cons : ∀ {n}, A → vec2 n → vec2 (n+1)
|
|
|
|
section
|
|
open vec2
|
|
|
|
definition map_4 {A : Type u} (f : A → A → A) : Π {n}, vec2 A n → vec2 A n → vec2 A n
|
|
| 0 nil nil := nil
|
|
| (n+1) (cons h₁ v₁) (cons h₂ v₂) := cons (f h₁ h₂) (map_4 v₁ v₂)
|
|
|
|
definition map_5 {A : Type u} (f : A → A → A) : Π {n}, vec2 A n → vec2 A n → vec2 A n
|
|
| ._ nil nil := nil
|
|
| ._ (@cons .A n h₁ v₁) (cons h₂ v₂) := cons (f h₁ h₂) (map_5 v₁ v₂)
|
|
|
|
/-
|
|
The following variant will be rejected by the new equation compiler.
|
|
In Lean2, the second equation is accepted because unassigned metavariables
|
|
occurring in patterns become new variables. This feature is too hackish.
|
|
-/
|
|
definition map_6 {A : Type u} (f : A → A → A) : Π {n}, vec2 A n → vec2 A n → vec2 A n
|
|
| ._ nil nil := nil
|
|
| ._ (cons h₁ v₁) (cons h₂ v₂) := cons (f h₁ h₂) (map_6 v₁ v₂)
|
|
end
|