quox/stdlib/fin.quox

260 lines
9.4 KiB
Text
Raw Normal View History

2024-05-06 13:24:02 -04:00
load "nat.quox"
load "either.quox"
load "maybe.quox"
load "sub.quox"
namespace nat.lt {
def0 LT : → ★ =
elim-pair¹ (λ _ _ ⇒ ★)
False -- 0 ≮ 0
(λ n p ⇒ True) -- 0 < succ n
(λ m p ⇒ False) -- succ m ≮ 0
(λ m n p ⇒ p) -- succ m < succ n ⇔ m < n
def0 irr : sub.Irr2 LT =
elim-pair (λ m n ⇒ (p q : LT m n) → p ≡ q : LT m n)
false.irr (λ _ _ ⇒ true.irr) (λ _ _ ⇒ false.irr) (λ _ _ p ⇒ p)
-- [todo] quantities (which will need to inline and adapt elim-pair)
def elimω : 0.(P : (m n : ) → LT m n → ★) →
ω.(0.(n : ) → P 0 (succ n) 'true) →
ω.(0.(m n : ) → 0.(lt : LT m n) →
ω.(P m n lt) → P (succ m) (succ n) lt) →
ω.(m n : ) → 0.(lt : LT m n) → P m n lt =
λ P p0s pss ⇒
elim-pairω (λ m n ⇒ 0.(lt : LT m n) → P m n lt)
(λ ff ⇒ void (P 0 0 ff) ff)
(λ n p tt ⇒ p0s n)
(λ m p ff ⇒ void (P (succ m) 0 ff) ff)
(λ m n p tt ⇒ pss m n tt (p tt))
def0 true-ty : (m n : ) → LT m n → LT m n ≡ True : ★ =
elim-pair¹ (λ m n ⇒ LT m n → LT m n ≡ True : ★)
(λ ff ⇒ void¹ (False ≡ True : ★) ff)
(λ n p tt ⇒ δ _ ⇒ True)
(λ m p ff ⇒ void¹ (False ≡ True : ★) ff)
(λ n m p tf ⇒ p tf)
def0 true-val :
(m n : ) → (lt : LT m n) → Eq (𝑖 ⇒ true-ty m n lt @𝑖) lt 'true =
let IsTrue : (m n : ) → LT m n → ★ =
λ m n lt ⇒ Eq (𝑖 ⇒ true-ty m n lt @𝑖) lt 'true in
elim-pair (λ m n ⇒ (lt : LT m n) → IsTrue m n lt)
(λ ff ⇒ void (IsTrue 0 0 ff) ff)
(λ n p tt ⇒ δ _ ⇒ 'true)
(λ m p ff ⇒ void (IsTrue (succ m) 0 ff) ff)
(λ n m p tf ⇒ p tf)
def revive : 0.(m n : ) → 0.(LT m n) → LT m n =
λ m n lt ⇒ coe (𝑘 ⇒ true-ty m n lt @𝑘) @1 @0 'true
def drop : 0.(A : ★) → 0.(m n : ) → LT m n → A → A =
λ A m n lt x ⇒ true.drop A (coe (𝑖 ⇒ true-ty m n lt @𝑖) lt) x
def0 succ-both : (m n : ) → LT m n → LT (succ m) (succ n) =
λ m n p ⇒ p
def0 succ-right : (m n : ) → LT m n → LT m (succ n) =
λ m n lt ⇒
elimω (λ m n _ ⇒ LT m (succ n))
(λ _ ⇒ 'true)
(λ _ _ _ ih ⇒ ih)
m n lt
def0 right-is-succ : (m n : ) → LT m n → IsSucc n =
λ m n lt ⇒
elimω (λ _ n _ ⇒ IsSucc n) (λ _ ⇒ 'true) (λ _ _ _ _ ⇒ 'true) m n lt
def right-has-succ : 0.(m : ) → (n : ) → 0.(LT m n) → HasSucc n =
λ m n lt ⇒
case n return n' ⇒ 0.(LT m n') → HasSucc n' of {
0 ⇒ λ lt ⇒ void (HasSucc 0) (right-is-succ m 0 lt);
succ n ⇒ λ _ ⇒ (n, [δ _ ⇒ succ n])
} lt
def0 right-not-zero : (m : ) → Not (LT m 0) =
λ m ⇒ case m return m' ⇒ Not (LT m' 0) of { 0 ⇒ λ v ⇒ v; succ _ ⇒ λ v ⇒ v }
def0 plus-right : (m n₀ n₁ : ) → LT m n₀ → LT m (plus n₀ n₁) =
λ m n₀ n₁ lt ⇒
elimω (λ m n _ ⇒ LT m (plus n n₁)) (λ _ ⇒ 'true) (λ _ _ _ ih ⇒ ih) m n₀ lt
#[compile-scheme "(lambda% (m n) (if (< m n) dec.Yes dec.No))"]
def lt? : ω.(m n : ) → Dec (LT m n) =
elim-pairω (λ m n ⇒ Dec (LT m n))
(No (LT 0 0) (λ v ⇒ v))
(λ n p ⇒ Yes (LT 0 (succ n)) 'true)
(λ m p ⇒ No (LT (succ m) 0) (λ v ⇒ v))
(λ m n p ⇒
dec.elim (LT m n) (λ _ ⇒ Dec (LT (succ m) (succ n)))
(λ yes ⇒ Yes (LT (succ m) (succ n)) yes)
(λ no ⇒ No (LT (succ m) (succ n)) no) p)
def0 irrefl : (m n : ) → LT m n → Not (m ≡ n : ) =
λ m n lt ⇒
elimω (λ m n _ ⇒ Not (m ≡ n : ))
(λ n eq ⇒ zero-not-succ n eq)
(λ m n _ ih eq ⇒ ih (succ-inj m n eq))
m n lt
def0 asym : (m n : ) → LT m n → Not (LT n m) =
λ m n lt ⇒
elimω (λ m n _ ⇒ Not (LT n m)) (λ _ ff ⇒ ff) (λ _ _ _ ih ff ⇒ ih ff) m n lt
def0 trans : (n₀ n₁ n₂ : ) → LT n₀ n₁ → LT n₁ n₂ → LT n₀ n₂ =
λ n₀ n₁ n₂ lt₀₁ lt₁₂ ⇒
elimω (λ n₀ n₁ lt₀₁ ⇒ (n₂ : ) → (lt₁₂ : LT n₁ n₂) → LT n₀ n₂)
(λ n₁ n₂ ⇒
case n₂ return n₂' ⇒ LT (succ n₁) n₂' → LT 0 n₂' of {
0 ⇒ λ v ⇒ v;
succ _ ⇒ λ _ ⇒ 'true
})
(λ n₀ n₁ lt₀₁ ih n₂ ⇒
case n₂ return n₂' ⇒ LT (succ n₁) n₂' → LT (succ n₀) n₂' of {
0 ⇒ λ v ⇒ v;
succ n₂ ⇒ λ lt₁₂ ⇒ ih n₂ lt₁₂
})
n₀ n₁ lt₀₁ n₂ lt₁₂
}
namespace nat {
def0 LT = lt.LT
def lt? = lt.lt?
}
namespace fin {
def0 Bounded : → ★ = λ n i ⇒ nat.LT i n
def0 Fin : → ★ = λ n ⇒ Sub (Bounded n)
def fin : 0.(n : ) → (i : ) → 0.(Bounded n i) → Fin n =
λ n ⇒ sub.sub (Bounded n)
def val : 0.(n : ) → Fin n → =
λ n ⇒ sub.val (Bounded n)
def0 val-eq : (n : ) → (i j : Fin n) → val n i ≡ val n j : → i ≡ j : Fin n =
λ n ⇒ sub.sub-eq (Bounded n) (λ i ⇒ nat.lt.irr i n)
def0 proof : (n : ) → (i : Fin n) → nat.LT (val n i) n =
λ n ⇒ sub.proof (Bounded n)
def0 no-fin0 : Not (Fin 0) =
λ f0 ⇒ case f0 return False of { (i, lt) ⇒
nat.lt.right-not-zero i (get0 (nat.LT i 0) lt)
}
def fin? : ω.(n i : ) → Maybe (Fin n) =
λ n ⇒ sub.sub? (Bounded n) (λ i ⇒ nat.lt? i n)
def F0 : 0.(n : ) → Fin (succ n) =
λ n ⇒ fin (succ n) 0 'true
def FS : 0.(n : ) → Fin n → Fin (succ n) =
λ n i ⇒ fin (succ n) (succ (val n i)) (proof n i)
def weak : 0.(m n : ) → 0.(nat.LT m n) → Fin m → Fin n =
λ m n mn i' ⇒
let i = val m i'; 0.im = proof m i' in
fin n i (nat.lt.trans i m n im mn)
def bound-has-succ : (n : ) → 0.(Fin n) → nat.HasSucc n =
λ n i ⇒ nat.lt.right-has-succ (fst i) n (get0 (nat.LT (fst i) n) (snd i))
def elim' :
0.(P : (n i : ) → nat.LT i n → ★) →
1.(pz : 0.(n : ) → P (succ n) 0 'true) →
ω.(ps : 0.(n i : ) → 0.(lt : nat.LT i n) →
P n i lt → P (succ n) (succ i) lt) →
0.(n : ) → (i : ) → 0.(lt : nat.LT i n) → P n i lt =
λ P pz ps n i lt ⇒
case i return i' ⇒ 0.(n : ) → 0.(lt : nat.LT i' n) → P n i' lt of {
0 ⇒ λ n lt ⇒
let0 npp = nat.lt.right-has-succ 0 n lt;
p = nat.has-succ.val n npp;
np = nat.has-succ.proof n npp in
coe (𝑘 ⇒ P (np @𝑘) 0 (coe (𝑙 ⇒ nat.LT 0 (np @𝑙)) @0 @𝑘 lt)) @1 @0
(pz p);
succ i, ih ⇒ λ n lt ⇒
let 0.npp = nat.lt.right-has-succ (succ i) n lt;
0.p = nat.has-succ.val n npp;
0.np = nat.has-succ.proof n npp;
0.lt' : nat.LT i p = coe (𝑘 ⇒ nat.LT (succ i) (np @𝑘)) lt;
0.lteq : Eq (𝑘 ⇒ nat.LT (succ i) (np @𝑘)) lt lt' =
δ 𝑘 ⇒ coe (𝑙 ⇒ nat.LT (succ i) (np @𝑙)) @0 @𝑘 lt;
1.almost : P (succ p) (succ i) lt' = ps p i lt' (ih p lt') in
coe (𝑘 ⇒ P (np @𝑘) (succ i) (lteq @𝑘)) @1 @0 almost;
} n lt
def elim : 0.(P : (n : ) → Fin n → ★) →
(pz : 0.(n : ) → P (succ n) (F0 n)) →
(ps : 0.(n : ) → 0.(i : Fin n) →
P n i → P (succ n) (FS n i)) →
0.(n : ) → (i : Fin n) → P n i =
λ P pz ps n ilt ⇒
case ilt return ilt' ⇒ P n ilt' of { (i, lt) ⇒
let0 lt = get0 (nat.LT i n) lt in
drop0 (nat.LT i n) (P n (i, [lt])) lt
(elim' (λ n i lt ⇒ P n (i, [lt])) pz (λ n i lt ⇒ ps n (i, [lt])) n i lt)
}
{-
def elim : 0.(P : (n : ) → Fin n → ★) →
(pz : 0.(n : ) → P (succ n) (F0 n)) →
(ps : 0.(n : ) → 0.(i : Fin n) →
P n i → P (succ n) (FS n i)) →
0.(n : ) → (i : Fin n) → P n i =
λ P pz ps n ilt ⇒
let i = val n ilt; 0.lt : nat.LT i n = proof n ilt;
0.pp = nat.lt.right-has-succ i n lt;
0.p = nat.has-succ.val n pp; 0.np = nat.has-succ.proof n pp;
0.RES : → ★ =
λ i n ⇒ (lt : nat.LT i n) × P n (i, [lt]);
res : RES i (succ p) =
case i
return i' ⇒ 0.(p : ) → 0.(nat.LT i' (succ p)) → RES i' (succ p)
of {
0 ⇒ λ p _ ⇒ ('true, pz p);
succ i, IH ⇒ λ p lt ⇒
let 0.qq = nat.lt.right-has-succ i p lt;
0.q = nat.has-succ.val p qq; 0.pq = nat.has-succ.proof p qq;
0.lt : nat.LT i (succ q) = coe (𝑘 ⇒ nat.LT i (pq @𝑘)) lt;
in
case IH q lt return RES (succ i) (succ p) of { (lt', ih') ⇒
let lt : nat.LT (succ i) (succ p) =
coe (𝑘 ⇒ nat.LT i (pq @𝑘)) @1 @0 lt';
ih : P p (i, [lt]) =
coe (𝑘 ⇒ P (pq @𝑘) (i, [coe (𝑙 ⇒ nat.LT i (pq @𝑙)) @1 @𝑘 lt']))
@1 @0 ih';
res : P (succ p) (succ i, [lt]) =
ps p (i, [lt]) ih;
in
(lt, res)
}
} p (coe (𝑘 ⇒ nat.LT i (np @𝑘)) lt);
in
case coe (𝑘 ⇒ RES i (np @𝑘)) @1 @0 res
return P n ilt
of { (lt', res) ⇒
nat.lt.drop (P n ilt) i n lt' res
}
-}
}
def0 Fin = fin.Fin
def F0 = fin.F0
def FS = fin.FS