fix nat elim quantities

This commit is contained in:
rhiannon morris 2023-04-01 16:01:53 +02:00
parent 036e2bd4a5
commit 15f6f4c8a4
4 changed files with 41 additions and 9 deletions

View file

@ -10,7 +10,8 @@ import Data.DPair
public export public export
interface Eq q => IsQty q where interface Eq q => IsQty q where
zero, one : q zero, one, any : q
(+), (*) : q -> q -> q (+), (*) : q -> q -> q
lub : q -> q -> Maybe q lub : q -> q -> Maybe q
@ -20,6 +21,12 @@ interface Eq q => IsQty q where
isZero : Dec1 IsZero isZero : Dec1 IsZero
zeroIsZero : IsZero zero zeroIsZero : IsZero zero
||| true if bindings of this quantity can be used any number of times.
||| this is needed for natural elimination
IsAny : Pred q
isAny : Dec1 IsAny
anyIsAny : IsAny any
||| ``p `Compat` q`` if it is ok for a binding of quantity `q` to be used ||| ``p `Compat` q`` if it is ok for a binding of quantity `q` to be used
||| exactly `p` times. e.g. ``1 `Compat` 1``, ``1 `Compat` ω``. ||| exactly `p` times. e.g. ``1 `Compat` 1``, ``1 `Compat` ω``.
||| if ``π `lub` ρ`` exists, then both `π` and `ρ` must be compatible with it ||| if ``π `lub` ρ`` exists, then both `π` and `ρ` must be compatible with it
@ -38,7 +45,8 @@ interface Eq q => IsQty q where
||| quantity. so not exact usage counts, maybe. ||| quantity. so not exact usage counts, maybe.
IsGlobal : Pred q IsGlobal : Pred q
isGlobal : Dec1 IsGlobal isGlobal : Dec1 IsGlobal
zeroIsGlobal : forall pi. IsZero pi -> IsGlobal zero zeroIsGlobal : forall pi. IsZero pi -> IsGlobal pi
anyIsGlobal : forall pi. IsAny pi -> IsGlobal pi
||| prints in a form that can be a suffix of "case" ||| prints in a form that can be a suffix of "case"
prettySuffix : Pretty.HasEnv m => q -> m (Doc HL) prettySuffix : Pretty.HasEnv m => q -> m (Doc HL)
@ -74,6 +82,10 @@ public export %inline
gzero : IsQty q => GQty q gzero : IsQty q => GQty q
gzero = Element zero $ zeroIsGlobal zeroIsZero gzero = Element zero $ zeroIsGlobal zeroIsZero
public export %inline
gany : IsQty q => GQty q
gany = Element any $ anyIsGlobal anyIsAny
export %inline export %inline
globalToSubj : IsQty q => GQty q -> SQty q globalToSubj : IsQty q => GQty q -> SQty q
globalToSubj q = if isYes $ isZero q.fst then szero else sone globalToSubj q = if isYes $ isZero q.fst then szero else sone

View file

@ -106,6 +106,7 @@ public export
IsQty Three where IsQty Three where
zero = Zero zero = Zero
one = One one = One
any = Any
(+) = plus (+) = plus
(*) = times (*) = times
@ -116,6 +117,10 @@ IsQty Three where
isZero = decEq Zero isZero = decEq Zero
zeroIsZero = Refl zeroIsZero = Refl
IsAny = Equal Three.Any
isAny = decEq Any
anyIsAny = Refl
Compat = Compat3 Compat = Compat3
compat = compat3 compat = compat3
@ -128,6 +133,7 @@ IsQty Three where
IsGlobal = IsGlobal3 IsGlobal = IsGlobal3
isGlobal = isGlobal3 isGlobal = isGlobal3
zeroIsGlobal = \Refl => GZero zeroIsGlobal = \Refl => GZero
anyIsGlobal = \Refl => GAny
prettySuffix = pretty0M prettySuffix = pretty0M

View file

@ -386,16 +386,13 @@ parameters {auto _ : IsQty q}
sucCtx = extendTyN [< (pisg, p, Nat), (pi', ih, ret.term)] ctx sucCtx = extendTyN [< (pisg, p, Nat), (pi', ih, ret.term)] ctx
sucType = substCaseSuccRet ret sucType = substCaseSuccRet ret
sucout :< qp :< qih <- checkC sucCtx sg suc.term sucType sucout :< qp :< qih <- checkC sucCtx sg suc.term sucType
let Just armout = lubs ctx [zerout, sucout]
| _ => throw $ BadCaseQtys ctx $
[(zerout, Zero), (sucout, Succ $ FT $ unq p)]
expectCompatQ qih (pi' * sg.fst) expectCompatQ qih (pi' * sg.fst)
-- [fixme] better error here -- [fixme] better error here
expectCompatQ (qp + qih) pisg expectCompatQ (qp + qih) pisg
-- then Ψ | Γ ⊢ case ⋯ ⇒ A[n] ⊳ πΣn + (Σz ∧ Σs) -- then Ψ | Γ ⊢ case ⋯ ⇒ A[n] ⊳ πΣn + Σz + ωΣs
pure $ InfRes { pure $ InfRes {
type = sub1 ret n, type = sub1 ret n,
qout = pi * nres.qout + armout qout = pi * nres.qout + zerout + any * sucout
} }
infer' ctx sg (CaseBox pi box ret body) = do infer' ctx sg (CaseBox pi box ret body) = do

View file

@ -401,6 +401,23 @@ tests = "typechecker" :- [
todo "nat elim" todo "nat elim"
], ],
"natural elim" :- [
note "1 · λ n ⇒ case1 n return of { zero ⇒ 0; succ n ⇒ n }",
note " ⇐ 1.",
testTC "pred" $
check_ empty sone
([< "n"] :\\ E (CaseNat One Zero (BV 0) (SN Nat)
Zero (SY [< "n", Unused] $ BVT 1)))
(Arr One Nat Nat),
note "1 · λ m n ⇒ case1 m return of { zero ⇒ n; succ _, 1.p ⇒ succ p }",
note " ⇐ 1. → 1. → 1.",
testTC "plus" $
check_ empty sone
([< "m", "n"] :\\ E (CaseNat One One (BV 1) (SN Nat)
(BVT 0) (SY [< Unused, "p"] $ Succ $ BVT 0)))
(Arr One Nat $ Arr One Nat Nat)
],
"box types" :- [ "box types" :- [
testTC "0 · [0.] ⇐ ★₀" $ testTC "0 · [0.] ⇐ ★₀" $
check_ empty szero (BOX Zero Nat) (TYPE 0), check_ empty szero (BOX Zero Nat) (TYPE 0),