When the type of an `example` is a proposition,
we should elaborate on them as we elaborate on theorems.
This is particularly important for examples that are often
used in educational material.
Recall that when elaborating theorem headers, we convert unassigned
universe metavariables into universe parameters. The motivation is
that the proof of a theorem should not influence its statement.
However, before this commit, this was not the case for examples when
their type was a proposition.
This discrepancy often confused users.
Additionally, we considered extending the above behavior to definitions
when
1- When their type is a proposition. However, it still caused disruption
in Mathlib.
2- When their type is provided. That is, we would keep the current
behavior only if `: <type>` was omitted. This would make the elaborator
for `def` much closer to the one for `theorem`, but it proved to be too
restrictive.
For example, the following instance in `Core.lean` would fail:
```
instance {α : Sort u} [Setoid α] : HasEquiv α :=
⟨Setoid.r⟩
```
and we would have to write instead:
```
instance {α : Sort u} [Setoid α] : HasEquiv.{u, 0} α :=
⟨Setoid.r⟩
```
There are other failures like this in the core, and we assume many more
in Mathlib.
closes #4398
closes #4482 Remark: PR #4482 implements option 1 above. We may consider
it again in the future.
83 lines
2.3 KiB
Text
83 lines
2.3 KiB
Text
def Vec (α : Type u) (n : Nat) : Type u := { a : List α // a.length = n }
|
||
def Vec.nil : Vec α 0 := ⟨[], rfl⟩
|
||
def Vec.cons (a : α) (as : Vec α n) : Vec α (n+1) := ⟨a :: as.val, by simp [as.property]⟩
|
||
|
||
set_option pp.analyze false
|
||
set_option linter.unusedVariables false
|
||
set_option pp.mvars false
|
||
|
||
def Vec.casesOn
|
||
(motive : (n : Nat) → Vec α n → Sort v)
|
||
(n : Nat)
|
||
(as : Vec α n)
|
||
(nil : motive 0 Vec.nil)
|
||
(cons : (n : Nat) → (a : α) → (as : Vec α n) → (ih : motive n as) → motive (n+1) (Vec.cons a as))
|
||
: motive n as :=
|
||
let rec go (n : Nat) (as : List α) (h : as.length = n) : motive n ⟨as, h⟩ :=
|
||
match n, as, h with
|
||
| 0, [], _ => nil
|
||
| n+1, a::as, h =>
|
||
have : as.length = n := by injection h
|
||
have ih : motive n ⟨as, this⟩ := go n as this
|
||
cons n a ⟨as, this⟩ ih
|
||
match as with
|
||
| ⟨as, h⟩ => go n as h
|
||
|
||
/--
|
||
info: α : Type u_1
|
||
n✝ : Nat
|
||
a✝ : α
|
||
as✝ : Vec α n✝
|
||
x✝ n : Nat
|
||
a : α
|
||
as : Vec α n
|
||
ih : as = as
|
||
⊢ Vec.cons a as = Vec.cons a as
|
||
-/
|
||
#guard_msgs in
|
||
example (n : Nat) (a : α) (as : Vec α n) : Vec.cons a (Vec.cons a as) = Vec.cons a (Vec.cons a as) := by
|
||
induction n+2, Vec.cons a (Vec.cons a as) using Vec.casesOn
|
||
case nil => constructor
|
||
case cons n a as ih =>
|
||
trace_state
|
||
constructor
|
||
|
||
/--
|
||
info: α : Type u_1
|
||
n✝ : Nat
|
||
a✝ : α
|
||
as✝ : Vec α n✝
|
||
n : Nat
|
||
a : α
|
||
as : Vec α n
|
||
ih : n + 1 = n → HEq (Vec.cons a as) as → Vec.cons a as = Vec.cons a as
|
||
⊢ Vec.cons a as = Vec.cons a as
|
||
-/
|
||
#guard_msgs in
|
||
example (n : Nat) (a : α) (as : Vec α n) : Vec.cons a (Vec.cons a as) = Vec.cons a (Vec.cons a as) := by
|
||
cases n+2, Vec.cons a (Vec.cons a as) using Vec.casesOn
|
||
case nil => constructor
|
||
case cons n a as ih =>
|
||
trace_state
|
||
constructor
|
||
|
||
/--
|
||
info: α : Type u_1
|
||
n : Nat
|
||
a : α
|
||
as : Vec α n
|
||
n' : Nat
|
||
a' : α
|
||
as' : Vec α n'
|
||
h₁ : n + 2 = n' + 1
|
||
h₂ : HEq (Vec.cons a (Vec.cons a as)) (Vec.cons a' as')
|
||
ih : n' + 1 = n' → HEq (Vec.cons a' as') as' → Vec.cons a' as' = Vec.cons a' as'
|
||
⊢ Vec.cons a' as' = Vec.cons a' as'
|
||
-/
|
||
#guard_msgs in
|
||
example (n : Nat) (a : α) (as : Vec α n) : Vec.cons a (Vec.cons a as) = Vec.cons a (Vec.cons a as) := by
|
||
cases h₁ : n+2, h₂ : Vec.cons a (Vec.cons a as) using Vec.casesOn
|
||
case nil => constructor
|
||
case cons n' a' as' ih =>
|
||
trace_state
|
||
constructor
|