Write Nat/Unit/Empty/Id Eliminators Through NbE and Bidir Elaboration

This commit is contained in:
2026-04-19 13:55:05 +00:00
parent a154e2b98c
commit 85be37b1d6
8 changed files with 374 additions and 2 deletions
+80 -1
View File
@@ -23,6 +23,11 @@ mutual
let bodyTy cApp c vt
let u' check cxt u bodyTy
pure (.pair t' u')
| .refl, .id a t u => do
if ( conv cxt.lvl t u) then
pure .refl
else
throw s!"refl cannot inhabit {showTy cxt.lvl (.id a t u)} because the endpoints are not definitionally equal"
| .letE x a t u, ty => do
let (a', _) inferUniverse cxt a
let va := eval cxt.env a'
@@ -33,7 +38,7 @@ mutual
pure (.letE a' t' u')
| r, ty => do
let (t', ty') infer cxt r
if ( conv cxt.lvl ty' ty) then
if ( sub cxt.lvl ty' ty) then
pure t'
else
throw s!"type mismatch: expected {showTy cxt.lvl ty}, got {showTy cxt.lvl ty'}"
@@ -43,6 +48,80 @@ mutual
match cxt.lookup x with
| some (i, a) => pure (.var i, a)
| none => throw s!"unknown variable {x}"
| .nat => pure (.nat, .univ 0)
| .zero => pure (.zero, .nat)
| .succ t => do
let t' check cxt t .nat
pure (.succ t', .nat)
| .natElim n motive z k ih s scrut => do
let scrut' check cxt scrut .nat
let vscrut eval cxt.env scrut'
let (motiveBody', level) inferUniverse (cxt.bind n .nat) motive
let motive' : Tm := .lam motiveBody'
let vmotive eval cxt.env motive'
let zTy vApp vmotive .zero
let z' check cxt z zTy
let kCxt := cxt.bind k .nat
let ihTy vApp vmotive (.var cxt.lvl)
let stepTy vApp vmotive (.succ (.var cxt.lvl))
let stepBody' check (kCxt.bind ih ihTy) s stepTy
let step' : Tm := .lam (.lam stepBody')
let resultTy vApp vmotive vscrut
let _ := level
pure (.natElim motive' z' step' scrut', resultTy)
| .unit => pure (.unit, .univ 0)
| .triv => pure (.triv, .unit)
| .unitElim u motive t scrut => do
let scrut' check cxt scrut .unit
let vscrut eval cxt.env scrut'
let (motiveBody', level) inferUniverse (cxt.bind u .unit) motive
let motive' : Tm := .lam motiveBody'
let vmotive eval cxt.env motive'
let tTy vApp vmotive .triv
let t' check cxt t tTy
let resultTy vApp vmotive vscrut
let _ := level
pure (.unitElim motive' t' scrut', resultTy)
| .empty => pure (.empty, .univ 0)
| .emptyElim e motive scrut => do
let scrut' check cxt scrut .empty
let vscrut eval cxt.env scrut'
let (motiveBody', level) inferUniverse (cxt.bind e .empty) motive
let motive' : Tm := .lam motiveBody'
let vmotive eval cxt.env motive'
let resultTy vApp vmotive vscrut
let _ := level
pure (.emptyElim motive' scrut', resultTy)
| .id a t u => do
let (a', level) inferUniverse cxt a
let va eval cxt.env a'
let t' check cxt t va
let u' check cxt u va
pure (.id a' t' u', .univ level)
| .refl => throw "cannot infer type of refl, use an annotation"
| .idElim y p motive r target eq => do
let (eq', eqTy) infer cxt eq
match eqTy with
| .id a x rhs => do
let (target', targetTy) infer cxt target
if !( conv cxt.lvl targetTy a) then
throw s!"idElim target has type {showTy cxt.lvl targetTy}, but the equality lives over {showTy cxt.lvl a}"
let vtarget eval cxt.env target'
if !( conv cxt.lvl vtarget rhs) then
throw s!"idElim target {showTy cxt.lvl vtarget} does not match the equality endpoint {showTy cxt.lvl rhs}"
let eqVarTy : Val := .id a x (.var cxt.lvl)
let (motiveBody', level) inferUniverse ((cxt.bind y a).bind p eqVarTy) motive
let motive' : Tm := .lam (.lam motiveBody')
let vmotive eval cxt.env motive'
let reflTy vApp vmotive x
let reflTy vApp reflTy .refl
let r' check cxt r reflTy
let veq eval cxt.env eq'
let resultTy vApp vmotive vtarget
let resultTy vApp resultTy veq
let _ := level
pure (.idElim motive' r' target' eq', resultTy)
| _ => throw s!"expected Id type in idElim, got {showTy cxt.lvl eqTy}"
| .univ i => pure (.univ i, .univ (i + 1))
| .app t u => do
let (t', tty) infer cxt t