2023-12-01 12:52:23 -05:00
|
|
|
|
load "misc.quox";
|
|
|
|
|
load "bool.quox";
|
|
|
|
|
load "either.quox";
|
|
|
|
|
|
|
|
|
|
namespace nat {
|
|
|
|
|
|
|
|
|
|
def elim-0-1 :
|
|
|
|
|
0.(P : ℕ → ★) →
|
|
|
|
|
ω.(P 0) → ω.(P 1) →
|
|
|
|
|
ω.(0.(n : ℕ) → P n → P (succ n)) →
|
|
|
|
|
(n : ℕ) → P n =
|
|
|
|
|
λ P p0 p1 ps n ⇒
|
|
|
|
|
case n return n' ⇒ P n' of {
|
|
|
|
|
zero ⇒ p0;
|
|
|
|
|
succ n' ⇒
|
|
|
|
|
case n' return n'' ⇒ P (succ n'') of {
|
|
|
|
|
zero ⇒ p1;
|
|
|
|
|
succ n'', IH ⇒ ps (succ n'') IH
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-06 21:47:23 -05:00
|
|
|
|
def elim-pair' :
|
2023-12-01 12:52:23 -05:00
|
|
|
|
0.(P : ℕ → ℕ → ★) →
|
|
|
|
|
ω.(P 0 0) →
|
|
|
|
|
ω.(0.(n : ℕ) → P 0 n → P 0 (succ n)) →
|
|
|
|
|
ω.(0.(m : ℕ) → P m 0 → P (succ m) 0) →
|
|
|
|
|
ω.(0.(m n : ℕ) → P m n → P (succ m) (succ n)) →
|
|
|
|
|
ω.(m : ℕ) → (n : ℕ) → P m n =
|
|
|
|
|
λ P zz zs sz ss m ⇒
|
|
|
|
|
caseω m return m' ⇒ (n : ℕ) → P m' n of {
|
|
|
|
|
0 ⇒ λ n ⇒ case n return n' ⇒ P 0 n' of {
|
|
|
|
|
0 ⇒ zz;
|
|
|
|
|
succ n', ihn ⇒ zs n' ihn
|
|
|
|
|
};
|
|
|
|
|
succ m', ω.ihm ⇒ λ n ⇒ case n return n' ⇒ P (succ m') n' of {
|
|
|
|
|
0 ⇒ sz m' (ihm 0);
|
|
|
|
|
succ n' ⇒ ss m' n' (ihm n')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-06 21:47:23 -05:00
|
|
|
|
def elim-pairω :
|
|
|
|
|
0.(P : ℕ → ℕ → ★) →
|
|
|
|
|
ω.(P 0 0) →
|
|
|
|
|
ω.(0.(n : ℕ) → ω.(P 0 n) → P 0 (succ n)) →
|
|
|
|
|
ω.(0.(m : ℕ) → ω.(P m 0) → P (succ m) 0) →
|
|
|
|
|
ω.(0.(m n : ℕ) → ω.(P m n) → P (succ m) (succ n)) →
|
|
|
|
|
ω.(m n : ℕ) → P m n =
|
|
|
|
|
λ P zz zs sz ss m ⇒
|
|
|
|
|
caseω m return m' ⇒ ω.(n : ℕ) → P m' n of {
|
|
|
|
|
0 ⇒ λ n ⇒ caseω n return n' ⇒ P 0 n' of {
|
|
|
|
|
0 ⇒ zz;
|
|
|
|
|
succ n', ω.ihn ⇒ zs n' ihn
|
|
|
|
|
};
|
|
|
|
|
succ m', ω.ihm ⇒ λ n ⇒ caseω n return n' ⇒ P (succ m') n' of {
|
|
|
|
|
0 ⇒ sz m' (ihm 0);
|
|
|
|
|
succ n' ⇒ ss m' n' (ihm n')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-01 12:52:23 -05:00
|
|
|
|
|
2023-12-12 14:37:05 -05:00
|
|
|
|
def succ-boxω : [ω.ℕ] → [ω.ℕ] =
|
|
|
|
|
λ n ⇒ case n return [ω.ℕ] of { [n] ⇒ [succ n] }
|
|
|
|
|
|
|
|
|
|
#[compile-scheme "(lambda (n) n)"]
|
2023-12-01 12:52:23 -05:00
|
|
|
|
def dup : ℕ → [ω.ℕ] =
|
2023-12-12 14:37:05 -05:00
|
|
|
|
λ n ⇒ case n return [ω.ℕ] of {
|
|
|
|
|
0 ⇒ [0];
|
|
|
|
|
succ _, n! ⇒ succ-boxω n!
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def0 dup-ok : (n : ℕ) → dup n ≡ [n] : [ω.ℕ] =
|
|
|
|
|
λ n ⇒
|
|
|
|
|
case n return n' ⇒ dup n' ≡ [n'] : [ω.ℕ] of {
|
|
|
|
|
0 ⇒ δ 𝑖 ⇒ [0];
|
|
|
|
|
succ _, ih ⇒ δ 𝑖 ⇒ succ-boxω (ih @𝑖)
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-19 20:08:54 -05:00
|
|
|
|
def dup! : (n : ℕ) → Dup ℕ n =
|
2023-12-12 14:37:05 -05:00
|
|
|
|
dup-from-parts ℕ dup dup-ok
|
|
|
|
|
|
2023-12-01 12:52:23 -05:00
|
|
|
|
|
2023-12-06 21:47:23 -05:00
|
|
|
|
def drop : 0.(A : ★) → ℕ → A → A =
|
2023-12-12 14:37:05 -05:00
|
|
|
|
drop-from-dup ℕ dup
|
|
|
|
|
|
2023-12-06 21:47:23 -05:00
|
|
|
|
|
2023-12-01 12:52:23 -05:00
|
|
|
|
#[compile-scheme "(lambda% (m n) (+ m n))"]
|
|
|
|
|
def plus : ℕ → ℕ → ℕ =
|
|
|
|
|
λ m n ⇒
|
|
|
|
|
case m return ℕ of {
|
|
|
|
|
zero ⇒ n;
|
|
|
|
|
succ _, p ⇒ succ p
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#[compile-scheme "(lambda% (m n) (* m n))"]
|
|
|
|
|
def timesω : ℕ → ω.ℕ → ℕ =
|
|
|
|
|
λ m n ⇒
|
|
|
|
|
case m return ℕ of {
|
|
|
|
|
zero ⇒ zero;
|
|
|
|
|
succ _, t ⇒ plus n t
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
def times : ℕ → ℕ → ℕ =
|
|
|
|
|
λ m n ⇒ case dup n return ℕ of { [n] ⇒ timesω m n };
|
|
|
|
|
|
|
|
|
|
def pred : ℕ → ℕ = λ n ⇒ case n return ℕ of { zero ⇒ zero; succ n ⇒ n };
|
|
|
|
|
|
|
|
|
|
def pred-succ : ω.(n : ℕ) → pred (succ n) ≡ n : ℕ =
|
|
|
|
|
λ n ⇒ δ 𝑖 ⇒ n;
|
|
|
|
|
|
|
|
|
|
def0 succ-inj : (m n : ℕ) → succ m ≡ succ n : ℕ → m ≡ n : ℕ =
|
|
|
|
|
λ m n eq ⇒ δ 𝑖 ⇒ pred (eq @𝑖);
|
|
|
|
|
|
|
|
|
|
#[compile-scheme "(lambda% (m n) (max 0 (- m n)))"]
|
|
|
|
|
def minus : ℕ → ℕ → ℕ =
|
|
|
|
|
λ m n ⇒
|
|
|
|
|
(case n return ℕ → ℕ of {
|
|
|
|
|
zero ⇒ λ m ⇒ m;
|
|
|
|
|
succ _, f ⇒ λ m ⇒ f (pred m)
|
|
|
|
|
}) m;
|
|
|
|
|
|
|
|
|
|
|
2023-12-06 21:47:23 -05:00
|
|
|
|
def minω : ω.ℕ → ω.ℕ → ℕ =
|
|
|
|
|
elim-pairω (λ _ _ ⇒ ℕ) 0 (λ _ _ ⇒ 0) (λ _ _ ⇒ 0) (λ _ _ x ⇒ succ x)
|
|
|
|
|
|
|
|
|
|
def min : ℕ → ℕ → ℕ =
|
|
|
|
|
λ m n ⇒
|
|
|
|
|
case dup m return ℕ of { [m] ⇒ case dup n return ℕ of { [n] ⇒ minω m n } }
|
|
|
|
|
|
|
|
|
|
|
2023-12-01 12:52:23 -05:00
|
|
|
|
def0 IsSucc : ℕ → ★ =
|
|
|
|
|
λ n ⇒ case n return ★ of { zero ⇒ False; succ _ ⇒ True };
|
|
|
|
|
|
|
|
|
|
def isSucc? : ω.(n : ℕ) → Dec (IsSucc n) =
|
|
|
|
|
λ n ⇒
|
|
|
|
|
caseω n return n' ⇒ Dec (IsSucc n') of {
|
|
|
|
|
zero ⇒ No (IsSucc zero) (λ v ⇒ v);
|
|
|
|
|
succ n ⇒ Yes (IsSucc (succ n)) 'true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
def zero-not-succ : 0.(m : ℕ) → Not (zero ≡ succ m : ℕ) =
|
|
|
|
|
λ m eq ⇒ coe (𝑖 ⇒ IsSucc (eq @𝑖)) @1 @0 'true;
|
|
|
|
|
|
|
|
|
|
def succ-not-zero : 0.(m : ℕ) → Not (succ m ≡ zero : ℕ) =
|
|
|
|
|
λ m eq ⇒ coe (𝑖 ⇒ IsSucc (eq @𝑖)) 'true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def0 not-succ-self : (m : ℕ) → Not (m ≡ succ m : ℕ) =
|
|
|
|
|
λ m ⇒
|
|
|
|
|
case m return m' ⇒ Not (m' ≡ succ m' : ℕ) of {
|
|
|
|
|
zero ⇒ zero-not-succ 0;
|
|
|
|
|
succ n, ω.ih ⇒ λ eq ⇒ ih (succ-inj n (succ n) eq)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-12-19 20:08:54 -05:00
|
|
|
|
def divmod : ℕ → ℕ → ℕ × ℕ =
|
|
|
|
|
-- https://coq.inria.fr/doc/V8.18.0/stdlib/Coq.Init.Nat.html#divmod
|
|
|
|
|
letω divmod' : ℕ → ω.ℕ → ℕ → ℕ → ℕ × ℕ =
|
|
|
|
|
λ x ⇒
|
|
|
|
|
case x return ω.ℕ → ℕ → ℕ → ℕ × ℕ of {
|
|
|
|
|
0 ⇒ λ y q u ⇒ (q, u);
|
|
|
|
|
succ _, 1.f' ⇒ λ y q u ⇒
|
|
|
|
|
case u return ℕ × ℕ of {
|
|
|
|
|
0 ⇒ f' y (succ q) y;
|
|
|
|
|
succ u' ⇒ f' y q u'
|
|
|
|
|
}
|
|
|
|
|
} in
|
|
|
|
|
λ x y ⇒
|
|
|
|
|
case y return ℕ × ℕ of {
|
|
|
|
|
0 ⇒ drop (ℕ × ℕ) x (0, 0);
|
|
|
|
|
succ y' ⇒
|
|
|
|
|
case dup y' return ℕ × ℕ of { [y'] ⇒
|
|
|
|
|
case divmod' x y' 0 y' return ℕ × ℕ of { (d, m) ⇒ (d, minus y' m) }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def div : ℕ → ℕ → ℕ =
|
|
|
|
|
λ x y ⇒ case divmod x y return ℕ of { (d, m) ⇒ drop ℕ m d }
|
|
|
|
|
|
|
|
|
|
def mod : ℕ → ℕ → ℕ =
|
|
|
|
|
λ x y ⇒ case divmod x y return ℕ of { (d, m) ⇒ drop ℕ d m }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def0 div-5-2 : div 5 2 ≡ 2 : ℕ = δ 𝑖 ⇒ 2
|
|
|
|
|
def0 mod-5-2 : mod 5 2 ≡ 1 : ℕ = δ 𝑖 ⇒ 1
|
|
|
|
|
|
|
|
|
|
|
2023-12-01 12:52:23 -05:00
|
|
|
|
#[compile-scheme "(lambda% (m n) (if (= m n) Yes No))"]
|
|
|
|
|
def eq? : DecEq ℕ =
|
2023-12-06 21:47:23 -05:00
|
|
|
|
λ m n ⇒
|
|
|
|
|
elim-pair' (λ m n ⇒ Dec (m ≡ n : ℕ))
|
|
|
|
|
(Yes (0 ≡ 0 : ℕ) (δ 𝑖 ⇒ 0))
|
|
|
|
|
(λ n p ⇒
|
|
|
|
|
dec.drop (0 ≡ n : ℕ) (Dec (0 ≡ succ n : ℕ)) p
|
|
|
|
|
(No (0 ≡ succ n : ℕ) (λ zs ⇒ zero-not-succ n zs)))
|
|
|
|
|
(λ m p ⇒
|
|
|
|
|
dec.drop (m ≡ 0 : ℕ) (Dec (succ m ≡ 0 : ℕ)) p
|
|
|
|
|
(No (succ m ≡ 0 : ℕ) (λ sz ⇒ succ-not-zero m sz)))
|
|
|
|
|
(λ m n ⇒
|
|
|
|
|
dec.elim (m ≡ n : ℕ) (λ _ ⇒ Dec (succ m ≡ succ n : ℕ))
|
|
|
|
|
(λ yy ⇒ Yes (succ m ≡ succ n : ℕ) (δ 𝑖 ⇒ succ (yy @𝑖)))
|
|
|
|
|
(λ nn ⇒ No (succ m ≡ succ n : ℕ) (λ yy ⇒ nn (succ-inj m n yy))))
|
|
|
|
|
m n
|
2023-12-01 12:52:23 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def0 Ordering : ★ = {lt, eq, gt}
|
|
|
|
|
|
2023-12-06 21:47:23 -05:00
|
|
|
|
namespace ordering {
|
|
|
|
|
def from : 0.(A : ★) → ω.A → ω.A → ω.A → Ordering → A =
|
|
|
|
|
λ A lt eq gt o ⇒
|
|
|
|
|
case o return A of { 'lt ⇒ lt; 'eq ⇒ eq; 'gt ⇒ gt }
|
|
|
|
|
|
|
|
|
|
def drop : 0.(A : ★) → Ordering → A → A =
|
|
|
|
|
λ A o x ⇒ case o return A of { 'lt ⇒ x; 'eq ⇒ x; 'gt ⇒ x }
|
2023-12-01 12:52:23 -05:00
|
|
|
|
|
2023-12-06 21:47:23 -05:00
|
|
|
|
def eq : Ordering → Ordering → Bool =
|
|
|
|
|
λ x y ⇒
|
|
|
|
|
case x return Bool of {
|
|
|
|
|
'lt ⇒ case y return Bool of { 'lt ⇒ 'true; 'eq ⇒ 'false; 'gt ⇒ 'false };
|
|
|
|
|
'eq ⇒ case y return Bool of { 'lt ⇒ 'false; 'eq ⇒ 'true; 'gt ⇒ 'false };
|
|
|
|
|
'gt ⇒ case y return Bool of { 'lt ⇒ 'false; 'eq ⇒ 'false; 'gt ⇒ 'true };
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-01 12:52:23 -05:00
|
|
|
|
|
|
|
|
|
def compareω : ω.ℕ → ℕ → Ordering =
|
2023-12-06 21:47:23 -05:00
|
|
|
|
elim-pair' (λ _ _ ⇒ Ordering)
|
2023-12-01 12:52:23 -05:00
|
|
|
|
'eq
|
2023-12-06 21:47:23 -05:00
|
|
|
|
(λ _ o ⇒ ordering.drop Ordering o 'lt)
|
|
|
|
|
(λ _ o ⇒ ordering.drop Ordering o 'gt)
|
2023-12-01 12:52:23 -05:00
|
|
|
|
(λ _ _ x ⇒ x)
|
|
|
|
|
|
|
|
|
|
def compare : ℕ → ℕ → Ordering =
|
2023-12-06 21:47:23 -05:00
|
|
|
|
λ m n ⇒ case dup m return Ordering of { [m] ⇒ compareω m n }
|
|
|
|
|
|
|
|
|
|
def lt : ω.ℕ → ω.ℕ → Bool = λ m n ⇒ ordering.eq (compare m n) 'lt
|
|
|
|
|
def eq : ω.ℕ → ω.ℕ → Bool = λ m n ⇒ ordering.eq (compare m n) 'eq
|
|
|
|
|
def gt : ω.ℕ → ω.ℕ → Bool = λ m n ⇒ ordering.eq (compare m n) 'gt
|
|
|
|
|
def ne : ω.ℕ → ω.ℕ → Bool = λ m n ⇒ bool.not (eq m n)
|
|
|
|
|
def le : ω.ℕ → ω.ℕ → Bool = λ m n ⇒ bool.not (gt m n)
|
|
|
|
|
def ge : ω.ℕ → ω.ℕ → Bool = λ m n ⇒ bool.not (lt m n)
|
2023-12-01 12:52:23 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def0 plus-zero : (m : ℕ) → m ≡ plus m 0 : ℕ =
|
|
|
|
|
λ m ⇒
|
|
|
|
|
case m return m' ⇒ m' ≡ plus m' 0 : ℕ of {
|
|
|
|
|
zero ⇒ δ _ ⇒ 0;
|
|
|
|
|
succ m', ih ⇒ δ 𝑖 ⇒ succ (ih @𝑖)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
def0 plus-succ : (m n : ℕ) → succ (plus m n) ≡ plus m (succ n) : ℕ =
|
|
|
|
|
λ m n ⇒
|
|
|
|
|
case m return m' ⇒ succ (plus m' n) ≡ plus m' (succ n) : ℕ of {
|
|
|
|
|
zero ⇒ δ _ ⇒ succ n;
|
|
|
|
|
succ _, ih ⇒ δ 𝑖 ⇒ succ (ih @𝑖)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
def0 times-zero : (m : ℕ) → 0 ≡ timesω m 0 : ℕ =
|
|
|
|
|
λ m ⇒
|
|
|
|
|
case m return m' ⇒ 0 ≡ timesω m' 0 : ℕ of {
|
|
|
|
|
zero ⇒ δ _ ⇒ zero;
|
|
|
|
|
succ m', ih ⇒ ih
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|