quox/stdlib/fin.quox

260 lines
9.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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