lean4-htt/library/init/datatypes.lean

497 lines
14 KiB
Text
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.

/-
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
Basic datatypes
-/
prelude
notation `Prop` := Type 0
notation `Type₂` := Type 2
notation `Type₃` := Type 3
universe variables u v
inductive poly_unit : Type u
| star : poly_unit
inductive unit : Type
| star : unit
inductive true : Prop
| intro : true
inductive false : Prop
inductive empty : Type
inductive eq {A : Type u} (a : A) : A → Prop
| refl : eq a
inductive heq {A : Type u} (a : A) : Π {B : Type u}, B → Prop
| refl : heq a
structure prod (A : Type u) (B : Type v) :=
(fst : A) (snd : B)
inductive and (a b : Prop) : Prop
| intro : a → b → and
def and.elim_left {a b : Prop} (H : and a b) : a :=
and.rec (λ Ha Hb, Ha) H
def and.left := @and.elim_left
def and.elim_right {a b : Prop} (H : and a b) : b :=
and.rec (λ Ha Hb, Hb) H
def and.right := @and.elim_right
inductive sum (A : Type u) (B : Type v)
| inl {} : A → sum
| inr {} : B → sum
attribute [reducible]
def sum.intro_left {A : Type u} (B : Type v) (a : A) : sum A B :=
sum.inl a
attribute [reducible]
def sum.intro_right (A : Type u) {B : Type v} (b : B) : sum A B :=
sum.inr b
inductive or (a b : Prop) : Prop
| inl {} : a → or
| inr {} : b → or
def or.intro_left {a : Prop} (b : Prop) (Ha : a) : or a b :=
or.inl Ha
def or.intro_right (a : Prop) {b : Prop} (Hb : b) : or a b :=
or.inr Hb
structure sigma {A : Type u} (B : A → Type v) :=
mk :: (fst : A) (snd : B fst)
-- pos_num and num are two auxiliary datatypes used when parsing numerals such as 13, 0, 26.
-- The parser will generate the terms (pos (bit1 (bit1 (bit0 one)))), zero, and (pos (bit0 (bit1 (bit1 one)))).
-- This representation can be coerced in whatever we want (e.g., naturals, integers, reals, etc).
inductive pos_num : Type
| one : pos_num
| bit1 : pos_num → pos_num
| bit0 : pos_num → pos_num
namespace pos_num
def succ (a : pos_num) : pos_num :=
pos_num.rec_on a (bit0 one) (λ n r, bit0 r) (λ n r, bit1 n)
end pos_num
inductive num : Type
| zero : num
| pos : pos_num → num
namespace num
open pos_num
def succ (a : num) : num :=
num.rec_on a (pos one) (λ p, pos (succ p))
end num
inductive bool : Type
| ff : bool
| tt : bool
inductive option (A : Type u)
| none {} : option
| some : A → option
export option (none some)
export bool (ff tt)
inductive list (T : Type u)
| nil {} : list
| cons : T → list → list
inductive nat
| zero : nat
| succ : nat → nat
/- Declare builtin and reserved notation -/
structure [class] has_zero (A : Type u) := (zero : A)
structure [class] has_one (A : Type u) := (one : A)
structure [class] has_add (A : Type u) := (add : A → A → A)
structure [class] has_mul (A : Type u) := (mul : A → A → A)
structure [class] has_inv (A : Type u) := (inv : A → A)
structure [class] has_neg (A : Type u) := (neg : A → A)
structure [class] has_sub (A : Type u) := (sub : A → A → A)
structure [class] has_div (A : Type u) := (div : A → A → A)
structure [class] has_dvd (A : Type u) := (dvd : A → A → Prop)
structure [class] has_mod (A : Type u) := (mod : A → A → A)
structure [class] has_le (A : Type u) := (le : A → A → Prop)
structure [class] has_lt (A : Type u) := (lt : A → A → Prop)
structure [class] has_append (A : Type u) := (append : A → A → A)
structure [class] has_andthen(A : Type u) := (andthen : A → A → A)
def zero {A : Type u} [has_zero A] : A := has_zero.zero A
def one {A : Type u} [has_one A] : A := has_one.one A
def add {A : Type u} [has_add A] : A → A → A := has_add.add
def mul {A : Type u} [has_mul A] : A → A → A := has_mul.mul
def sub {A : Type u} [has_sub A] : A → A → A := has_sub.sub
def div {A : Type u} [has_div A] : A → A → A := has_div.div
def dvd {A : Type u} [has_dvd A] : A → A → Prop := has_dvd.dvd
def mod {A : Type u} [has_mod A] : A → A → A := has_mod.mod
def neg {A : Type u} [has_neg A] : A → A := has_neg.neg
def inv {A : Type u} [has_inv A] : A → A := has_inv.inv
def le {A : Type u} [has_le A] : A → A → Prop := has_le.le
def lt {A : Type u} [has_lt A] : A → A → Prop := has_lt.lt
def append {A : Type u} [has_append A] : A → A → A := has_append.append
def andthen {A : Type u} [has_andthen A] : A → A → A := has_andthen.andthen
attribute [reducible]
def ge {A : Type u} [s : has_le A] (a b : A) : Prop := le b a
attribute [reducible]
def gt {A : Type u} [s : has_lt A] (a b : A) : Prop := lt b a
def bit0 {A : Type u} [s : has_add A] (a : A) : A := add a a
def bit1 {A : Type u} [s₁ : has_one A] [s₂ : has_add A] (a : A) : A := add (bit0 a) one
attribute [pattern] zero one bit0 bit1 add
attribute [instance]
def num_has_zero : has_zero num :=
⟨num.zero⟩
attribute [instance]
def num_has_one : has_one num :=
⟨num.pos pos_num.one⟩
attribute [instance]
def pos_num_has_one : has_one pos_num :=
⟨pos_num.one⟩
namespace pos_num
def is_one (a : pos_num) : bool :=
pos_num.rec_on a tt (λ n r, ff) (λ n r, ff)
def pred (a : pos_num) : pos_num :=
pos_num.rec_on a one (λ n r, bit0 n) (λ n r, bool.rec_on (is_one n) (bit1 r) one)
def size (a : pos_num) : pos_num :=
pos_num.rec_on a one (λ n r, succ r) (λ n r, succ r)
def add (a b : pos_num) : pos_num :=
pos_num.rec_on a
succ
(λ n f b, pos_num.rec_on b
(succ (bit1 n))
(λ m r, succ (bit1 (f m)))
(λ m r, bit1 (f m)))
(λ n f b, pos_num.rec_on b
(bit1 n)
(λ m r, bit1 (f m))
(λ m r, bit0 (f m)))
b
end pos_num
attribute [instance]
def pos_num_has_add : has_add pos_num :=
⟨pos_num.add⟩
namespace num
open pos_num
def add (a b : num) : num :=
num.rec_on a b (λ pa, num.rec_on b (pos pa) (λ pb, pos (pos_num.add pa pb)))
end num
attribute [instance]
def num_has_add : has_add num :=
⟨num.add⟩
def std.priority.default : num := 1000
def std.priority.max : num := 4294967295
namespace nat
protected def prio := num.add std.priority.default 100
protected def add (a b : nat) : nat :=
nat.rec a (λ b₁ r, nat.succ r) b
def of_pos_num (p : pos_num) : nat :=
pos_num.rec (succ zero) (λ n r, nat.add (nat.add r r) (succ zero)) (λ n r, nat.add r r) p
def of_num (n : num) : nat :=
num.rec zero (λ p, of_pos_num p) n
end nat
attribute pos_num_has_add pos_num_has_one num_has_zero num_has_one num_has_add
[instance, priority nat.prio]
attribute [instance, priority nat.prio]
def nat_has_zero : has_zero nat :=
⟨nat.zero⟩
attribute [instance, priority nat.prio]
def nat_has_one : has_one nat :=
⟨nat.succ (nat.zero)⟩
attribute [instance, priority nat.prio]
def nat_has_add : has_add nat :=
⟨nat.add⟩
/-
Global declarations of right binding strength
If a module reassigns these, it will be incompatible with other modules that adhere to these
conventions.
When hovering over a symbol, use "C-c C-k" to see how to input it.
-/
def std.prec.max : num := 1024 -- the strength of application, identifiers, (, [, etc.
def std.prec.arrow : num := 25
/-
The next def is "max + 10". It can be used e.g. for postfix operations that should
be stronger than application.
-/
def std.prec.max_plus :=
num.succ (num.succ (num.succ (num.succ (num.succ (num.succ (num.succ (num.succ (num.succ
(num.succ std.prec.max)))))))))
/- Logical operations and relations -/
reserve prefix `¬`:40
reserve prefix `~`:40
reserve infixr ` ∧ `:35
reserve infixr ` /\ `:35
reserve infixr ` \/ `:30
reserve infixr ` `:30
reserve infix ` <-> `:20
reserve infix ` ↔ `:20
reserve infix ` = `:50
reserve infix ` ≠ `:50
reserve infix ` ≈ `:50
reserve infix ` ~ `:50
reserve infix ` ≡ `:50
reserve infixl ` ⬝ `:75
reserve infixr ` ▸ `:75
reserve infixr ` ▹ `:75
/- types and type constructors -/
reserve infixr ` ⊕ `:30
reserve infixr ` × `:35
/- arithmetic operations -/
reserve infixl ` + `:65
reserve infixl ` - `:65
reserve infixl ` * `:70
reserve infixl ` / `:70
reserve infixl ` % `:70
reserve prefix `-`:100
reserve infix ` ^ `:80
reserve infixr ` ∘ `:90 -- input with \comp
reserve postfix `⁻¹`:std.prec.max_plus -- input with \sy or \-1 or \inv
reserve infix ` <= `:50
reserve infix ` ≤ `:50
reserve infix ` < `:50
reserve infix ` >= `:50
reserve infix ` ≥ `:50
reserve infix ` > `:50
/- boolean operations -/
reserve infixl ` && `:70
reserve infixl ` || `:65
/- set operations -/
reserve infix ` ∈ `:50
reserve infix ` ∉ `:50
reserve infixl ` ∩ `:70
reserve infixl ` `:65
reserve infix ` ⊆ `:50
reserve infix ` ⊇ `:50
reserve infix ` ' `:75 -- for the image of a set under a function
reserve infix ` '- `:75 -- for the preimage of a set under a function
/- other symbols -/
reserve infix ` `:50
reserve infixl ` ++ `:65
reserve infixr ` :: `:67
reserve infixl `; `:1
infix + := add
infix * := mul
infix - := sub
infix / := div
infix := dvd
infix % := mod
prefix - := neg
postfix ⁻¹ := inv
infix <= := le
infix >= := ge
infix ≤ := le
infix ≥ := ge
infix < := lt
infix > := gt
infix ++ := append
infix ; := andthen
/- eq basic support -/
notation a = b := eq a b
attribute [pattern]
def rfl {A : Type u} {a : A} : a = a := eq.refl a
namespace eq
variables {A : Type u}
variables {a b c a': A}
attribute [elab_as_eliminator]
theorem subst {P : A → Prop} (H₁ : a = b) (H₂ : P a) : P b :=
eq.rec H₂ H₁
theorem trans (H₁ : a = b) (H₂ : b = c) : a = c :=
subst H₂ H₁
theorem symm : a = b → b = a :=
λ h, eq.rec (refl a) h
end eq
notation H1 ▸ H2 := eq.subst H1 H2
attribute eq.subst [subst]
attribute eq.refl [refl]
attribute eq.trans [trans]
attribute eq.symm [symm]
/- sizeof -/
structure [class] has_sizeof (A : Type u) :=
(sizeof : A → nat)
def sizeof {A : Type u} [s : has_sizeof A] : A → nat :=
has_sizeof.sizeof
/-
Declare sizeof instances and lemmas for types declared before has_sizeof.
From now on, the inductive compiler will automatically generate sizeof instances and lemmas.
-/
/- Every type `A` has a default has_sizeof instance that just returns 0 for every element of `A` -/
attribute [instance]
def default_has_sizeof (A : Type u) : has_sizeof A :=
⟨λ a, nat.zero⟩
attribute [simp, defeq, simp.sizeof]
def default_has_sizeof_eq (A : Type u) (a : A) : @sizeof A (default_has_sizeof A) a = 0 :=
rfl
attribute [instance]
def nat_has_sizeof : has_sizeof nat :=
⟨λ a, a⟩
attribute [simp, defeq, simp.sizeof]
def sizeof_nat_eq (a : nat) : sizeof a = a :=
rfl
attribute [instance]
def prod_has_sizeof (A : Type u) (B : Type v) [has_sizeof A] [has_sizeof B] : has_sizeof (prod A B) :=
⟨λ p, prod.cases_on p (λ a b, 1 + sizeof a + sizeof b)⟩
attribute [simp, defeq, simp.sizeof]
def sizeof_prod_eq {A : Type u} {B : Type v} [has_sizeof A] [has_sizeof B] (a : A) (b : B) : sizeof (prod.mk a b) = 1 + sizeof a + sizeof b :=
rfl
attribute [instance]
def sum_has_sizeof (A : Type u) (B : Type v) [has_sizeof A] [has_sizeof B] : has_sizeof (sum A B) :=
⟨λ s, sum.cases_on s (λ a, 1 + sizeof a) (λ b, 1 + sizeof b)⟩
attribute [simp, defeq, simp.sizeof]
def sizeof_sum_eq_left {A : Type u} {B : Type v} [has_sizeof A] [has_sizeof B] (a : A) : sizeof (@sum.inl A B a) = 1 + sizeof a :=
rfl
attribute [simp, defeq, simp.sizeof]
def sizeof_sum_eq_right {A : Type u} {B : Type v} [has_sizeof A] [has_sizeof B] (b : B) : sizeof (@sum.inr A B b) = 1 + sizeof b :=
rfl
attribute [instance]
def sigma_has_sizeof (A : Type u) (B : A → Type v) [has_sizeof A] [∀ a, has_sizeof (B a)] : has_sizeof (sigma B) :=
⟨λ p, sigma.cases_on p (λ a b, 1 + sizeof a + sizeof b)⟩
attribute [simp, defeq, simp.sizeof]
def sizeof_sigma_eq {A : Type u} {B : A → Type v} [has_sizeof A] [∀ a, has_sizeof (B a)] (a : A) (b : B a) : sizeof (@sigma.mk A B a b) = 1 + sizeof a + sizeof b :=
rfl
attribute [instance]
def unit_has_sizeof : has_sizeof unit :=
⟨λ u, 1⟩
attribute [simp, defeq, simp.sizeof]
def sizeof_unit_eq (u : unit) : sizeof u = 1 :=
rfl
attribute [instance]
def poly_unit_has_sizeof : has_sizeof poly_unit :=
⟨λ u, 1⟩
attribute [simp, defeq, simp.sizeof]
def sizeof_poly_unit_eq (u : poly_unit) : sizeof u = 1 :=
rfl
attribute [instance]
def bool_has_sizeof : has_sizeof bool :=
⟨λ u, 1⟩
attribute [simp, defeq, simp.sizeof]
def sizeof_bool_eq (b : bool) : sizeof b = 1 :=
rfl
attribute [instance]
def pos_num_has_sizeof : has_sizeof pos_num :=
⟨λ p, nat.of_pos_num p⟩
attribute [simp, defeq, simp.sizeof]
def sizeof_pos_num_eq (p : pos_num) : sizeof p = nat.of_pos_num p :=
rfl
attribute [instance]
def num_has_sizeof : has_sizeof num :=
⟨λ p, nat.of_num p⟩
attribute [simp, defeq, simp.sizeof]
def sizeof_num_eq (n : num) : sizeof n = nat.of_num n :=
rfl
attribute [instance]
def option_has_sizeof (A : Type u) [has_sizeof A] : has_sizeof (option A) :=
⟨λ o, option.cases_on o 1 (λ a, 1 + sizeof a)⟩
attribute [simp, defeq, simp.sizeof]
def sizeof_option_none_eq (A : Type u) [has_sizeof A] : sizeof (@none A) = 1 :=
rfl
attribute [simp, defeq, simp.sizeof]
def sizeof_option_some_eq {A : Type u} [has_sizeof A] (a : A) : sizeof (some a) = 1 + sizeof a :=
rfl
attribute [instance]
def list_has_sizeof (A : Type u) [has_sizeof A] : has_sizeof (list A) :=
⟨λ l, list.rec_on l 1 (λ a t ih, 1 + sizeof a + ih)⟩
attribute [simp, defeq, simp.sizeof]
def sizeof_list_nil_eq (A : Type u) [has_sizeof A] : sizeof (@list.nil A) = 1 :=
rfl
attribute [simp, defeq, simp.sizeof]
def sizeof_list_cons_eq {A : Type u} [has_sizeof A] (a : A) (l : list A) : sizeof (list.cons a l) = 1 + sizeof a + sizeof l :=
rfl
attribute [simp.sizeof]
lemma nat_add_zero (n : nat) : n + 0 = n := rfl