lean4-htt/library/init/core.lean
2017-05-01 13:52:17 -07:00

590 lines
16 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
notation, basic datatypes and type classes
-/
prelude
notation `Prop` := Sort 0
notation f ` $ `:1 a:0 := f a
/- 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 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 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 ` ⊂ `:50
reserve infix ` ⊃ `:50
reserve infix ` \ `:70
/- other symbols -/
reserve infix ` `:50
reserve infixl ` ++ `:65
reserve infixr ` :: `:67
reserve infixl `; `:1
universes u v w
/-- Gadget for optional parameter support. -/
@[reducible] def opt_param (α : Sort u) (default : α) : Sort u :=
α
/-- Gadget for marking output parameters in type classes. -/
@[reducible] def out_param (α : Sort u) : Sort u := α
notation `inout`:1024 a:0 := out_param a
inductive punit : Sort u
| star : punit
inductive unit : Type
| star : unit
/--
Gadget for defining thunks, thunk parameters have special treatment.
Example: given
def f (s : string) (t : thunk nat) : nat
an application
f "hello" 10
is converted into
f "hello" (λ _, 10)
-/
@[reducible] def thunk (α : Type u) : Type u :=
unit → α
inductive true : Prop
| intro : true
inductive false : Prop
inductive empty : Type
def not (a : Prop) := a → false
prefix `¬` := not
inductive eq {α : Sort u} (a : α) : α → Prop
| refl : eq a
init_quotient
inductive heq {α : Sort u} (a : α) : Π {β : Sort u}, β → Prop
| refl : heq a
structure prod (α : Type u) (β : Type v) :=
(fst : α) (snd : β)
/- Similar to prod, but α and β can be propositions.
We use this type internally to automatically generate the brec_on recursor. -/
structure pprod (α : Sort u) (β : Sort v) :=
(fst : α) (snd : β)
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
/- eq basic support -/
infix = := eq
attribute [refl] eq.refl
@[pattern] def rfl {α : Sort u} {a : α} : a = a := eq.refl a
@[elab_as_eliminator, subst]
lemma eq.subst {α : Sort u} {P : α → Prop} {a b : α} (h₁ : a = b) (h₂ : P a) : P b :=
eq.rec h₂ h₁
notation h1 ▸ h2 := eq.subst h1 h2
@[trans] lemma eq.trans {α : Sort u} {a b c : α} (h₁ : a = b) (h₂ : b = c) : a = c :=
h₂ ▸ h₁
@[symm] lemma eq.symm {α : Sort u} {a b : α} (h : a = b) : b = a :=
h ▸ rfl
infix == := heq
lemma eq_of_heq {α : Sort u} {a a' : α} (h : a == a') : a = a' :=
have ∀ (α' : Sort u) (a' : α') (h₁ : @heq α a α' a') (h₂ : α = α'), (eq.rec_on h₂ a : α') = a', from
λ (α' : Sort u) (a' : α') (h₁ : @heq α a α' a'), heq.rec_on h₁ (λ h₂ : α = α, rfl),
show (eq.rec_on (eq.refl α) a : α) = a', from
this α a' h (eq.refl α)
/- The following four lemmas could not be automatically generated when the
structures were declared, so we prove them manually here. -/
lemma prod.mk.inj {α : Type u} {β : Type v} {x₁ : α} {y₁ : β} {x₂ : α} {y₂ : β}
: (x₁, y₁) = (x₂, y₂) → and (x₁ = x₂) (y₁ = y₂) :=
λ h, prod.no_confusion h (λ h₁ h₂, ⟨h₁, h₂⟩)
lemma prod.mk.inj_arrow {α : Type u} {β : Type v} {x₁ : α} {y₁ : β} {x₂ : α} {y₂ : β}
: (x₁, y₁) = (x₂, y₂) → Π ⦃P : Sort w⦄, (x₁ = x₂ → y₁ = y₂ → P) → P :=
λ h₁ _ h₂, prod.no_confusion h₁ h₂
lemma pprod.mk.inj {α : Sort u} {β : Sort v} {x₁ : α} {y₁ : β} {x₂ : α} {y₂ : β}
: pprod.mk x₁ y₁ = pprod.mk x₂ y₂ → and (x₁ = x₂) (y₁ = y₂) :=
λ h, pprod.no_confusion h (λ h₁ h₂, ⟨h₁, h₂⟩)
lemma pprod.mk.inj_arrow {α : Type u} {β : Type v} {x₁ : α} {y₁ : β} {x₂ : α} {y₂ : β}
: (x₁, y₁) = (x₂, y₂) → Π ⦃P : Sort w⦄, (x₁ = x₂ → y₁ = y₂ → P) → P :=
λ h₁ _ h₂, prod.no_confusion h₁ h₂
inductive sum (α : Type u) (β : Type v)
| inl {} : α → sum
| inr {} : β → sum
inductive psum (α : Sort u) (β : Sort v)
| inl {} : α → psum
| inr {} : β → psum
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 {α : Type u} (β : α → Type v) :=
mk :: (fst : α) (snd : β fst)
structure psigma {α : Sort u} (β : α → Sort v) :=
mk :: (fst : α) (snd : β fst)
inductive pos_num : Type
| one : pos_num
| bit1 : pos_num → pos_num
| bit0 : pos_num → pos_num
namespace pos_num
def succ : pos_num → pos_num
| one := bit0 one
| (bit1 n) := bit0 (succ n)
| (bit0 n) := bit1 n
end pos_num
inductive num : Type
| zero : num
| pos : pos_num → num
namespace num
open pos_num
def succ : num → num
| zero := pos one
| (pos p) := pos (pos_num.succ p)
end num
inductive bool : Type
| ff : bool
| tt : bool
/- Remark: subtype must take a Sort instead of Type because of the axiom strong_indefinite_description. -/
structure subtype {α : Sort u} (p : α → Prop) :=
(val : α) (property : p val)
attribute [pp_using_anonymous_constructor] sigma psigma subtype pprod
class inductive decidable (p : Prop)
| is_false : ¬p → decidable
| is_true : p → decidable
@[reducible]
def decidable_pred {α : Sort u} (r : α → Prop) :=
Π (a : α), decidable (r a)
@[reducible]
def decidable_rel {α : Sort u} (r : αα → Prop) :=
Π (a b : α), decidable (r a b)
@[reducible]
def decidable_eq (α : Sort u) :=
decidable_rel (@eq α)
inductive option (α : Type u)
| none {} : option
| some : α → option
export option (none some)
export bool (ff tt)
inductive list (T : Type u)
| nil {} : list
| cons : T → list → list
notation h :: t := list.cons h t
notation `[` l:(foldr `, ` (h t, list.cons h t) list.nil `]`) := l
inductive nat
| zero : nat
| succ : nat → nat
structure unification_constraint :=
{α : Type u} (lhs : α) (rhs : α)
infix ` ≟ `:50 := unification_constraint.mk
infix ` =?= `:50 := unification_constraint.mk
structure unification_hint :=
(pattern : unification_constraint)
(constraints : list unification_constraint)
/- Declare builtin and reserved notation -/
class has_zero (α : Type u) := (zero : α)
class has_one (α : Type u) := (one : α)
class has_add (α : Type u) := (add : ααα)
class has_mul (α : Type u) := (mul : ααα)
class has_inv (α : Type u) := (inv : αα)
class has_neg (α : Type u) := (neg : αα)
class has_sub (α : Type u) := (sub : ααα)
class has_div (α : Type u) := (div : ααα)
class has_dvd (α : Type u) := (dvd : αα → Prop)
class has_mod (α : Type u) := (mod : ααα)
class has_le (α : Type u) := (le : αα → Prop)
class has_lt (α : Type u) := (lt : αα → Prop)
class has_append (α : Type u) := (append : ααα)
class has_andthen (α : Type u) := (andthen : ααα)
class has_union (α : Type u) := (union : ααα)
class has_inter (α : Type u) := (inter : ααα)
class has_sdiff (α : Type u) := (sdiff : ααα)
class has_subset (α : Type u) := (subset : αα → Prop)
class has_ssubset (α : Type u) := (ssubset : αα → Prop)
/- Type classes has_emptyc and has_insert are
used to implement polymorphic notation for collections.
Example: {a, b, c}. -/
class has_emptyc (α : Type u) := (emptyc : α)
class has_insert (α : inout Type u) (γ : Type v) := (insert : αγγ)
/- Type class used to implement the notation { a ∈ c | p a } -/
class has_sep (α : inout Type u) (γ : Type v) :=
(sep : (α → Prop) → γγ)
/- Type class for set-like membership -/
class has_mem (α : inout Type u) (γ : Type v) := (mem : αγ → Prop)
infix ∈ := has_mem.mem
notation a ∉ s := ¬ has_mem.mem a s
infix + := has_add.add
infix * := has_mul.mul
infix - := has_sub.sub
infix / := has_div.div
infix := has_dvd.dvd
infix % := has_mod.mod
prefix - := has_neg.neg
infix <= := has_le.le
infix ≤ := has_le.le
infix < := has_lt.lt
infix ++ := has_append.append
infix ; := has_andthen.andthen
notation `∅` := has_emptyc.emptyc _
infix := has_union.union
infix ∩ := has_inter.inter
infix ⊆ := has_subset.subset
infix ⊂ := has_ssubset.ssubset
infix \ := has_sdiff.sdiff
export has_append (append)
@[reducible] def ge {α : Type u} [has_le α] (a b : α) : Prop := has_le.le b a
@[reducible] def gt {α : Type u} [has_lt α] (a b : α) : Prop := has_lt.lt b a
infix >= := ge
infix ≥ := ge
infix > := gt
@[reducible] def superset {α : Type u} [has_subset α] (a b : α) : Prop := has_subset.subset b a
@[reducible] def ssuperset {α : Type u} [has_ssubset α] (a b : α) : Prop := has_ssubset.ssubset b a
infix ⊇ := superset
infix ⊃ := ssuperset
def bit0 {α : Type u} [s : has_add α] (a : α) : α := a + a
def bit1 {α : Type u} [s₁ : has_one α] [s₂ : has_add α] (a : α) : α := (bit0 a) + 1
attribute [pattern] has_zero.zero has_one.one bit0 bit1 has_add.add has_neg.neg
def insert {α : Type u} {γ : Type v} [has_insert α γ] : αγγ :=
has_insert.insert
/- The empty collection -/
def singleton {α : Type u} {γ : Type v} [has_emptyc γ] [has_insert α γ] (a : α) : γ :=
has_insert.insert a ∅
/- num, pos_num instances -/
instance : has_zero num :=
⟨num.zero⟩
instance : has_one num :=
⟨num.pos pos_num.one⟩
instance : has_one pos_num :=
⟨pos_num.one⟩
namespace pos_num
def is_one : pos_num → bool
| one := tt
| _ := ff
def pred : pos_num → pos_num
| one := one
| (bit1 n) := bit0 n
| (bit0 one) := one
| (bit0 n) := bit1 (pred n)
def size : pos_num → pos_num
| one := one
| (bit0 n) := succ (size n)
| (bit1 n) := succ (size n)
def add : pos_num → pos_num → pos_num
| one b := succ b
| a one := succ a
| (bit0 a) (bit0 b) := bit0 (add a b)
| (bit1 a) (bit1 b) := bit0 (succ (add a b))
| (bit0 a) (bit1 b) := bit1 (add a b)
| (bit1 a) (bit0 b) := bit1 (add a b)
end pos_num
instance : has_add pos_num :=
⟨pos_num.add⟩
namespace num
open pos_num
def add : num → num → num
| zero a := a
| b zero := b
| (pos a) (pos b) := pos (pos_num.add a b)
end num
instance : has_add num :=
⟨num.add⟩
def std.priority.default : num := 1000
def std.priority.max : num := 4294967295
/- nat basic instances -/
namespace nat
protected def prio := num.add std.priority.default 100
protected def add : nat → nat → nat
| a zero := a
| a (succ b) := succ (add a b)
/- We mark the following definitions as pattern to make sure they can be used in recursive equations,
and reduced by the equation compiler. -/
attribute [pattern] nat.add nat.add._main
def of_pos_num : pos_num → nat
| pos_num.one := succ zero
| (pos_num.bit0 a) := let r := of_pos_num a in nat.add r r
| (pos_num.bit1 a) := let r := of_pos_num a in succ (nat.add r r)
def of_num : num → nat
| num.zero := zero
| (num.pos p) := of_pos_num p
end nat
instance : has_zero nat := ⟨nat.zero⟩
instance : has_one nat := ⟨nat.succ (nat.zero)⟩
instance : 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)))))))))
reserve postfix `⁻¹`:std.prec.max_plus -- input with \sy or \-1 or \inv
postfix ⁻¹ := has_inv.inv
notation α × β := prod α β
-- notation for n-ary tuples
/- sizeof -/
class has_sizeof (α : Sort u) :=
(sizeof : α → nat)
def sizeof {α : Sort u} [s : has_sizeof α] : α → 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 `α` has a default has_sizeof instance that just returns 0 for every element of `α` -/
protected def default.sizeof (α : Sort u) : α → nat
| a := 0
instance default_has_sizeof (α : Sort u) : has_sizeof α :=
⟨default.sizeof α⟩
protected def nat.sizeof : nat → nat
| n := n
instance : has_sizeof nat :=
⟨nat.sizeof⟩
protected def prod.sizeof {α : Type u} {β : Type v} [has_sizeof α] [has_sizeof β] : (prod α β) → nat
| ⟨a, b⟩ := 1 + sizeof a + sizeof b
instance (α : Type u) (β : Type v) [has_sizeof α] [has_sizeof β] : has_sizeof (prod α β) :=
⟨prod.sizeof⟩
protected def sum.sizeof {α : Type u} {β : Type v} [has_sizeof α] [has_sizeof β] : (sum α β) → nat
| (sum.inl a) := 1 + sizeof a
| (sum.inr b) := 1 + sizeof b
instance (α : Type u) (β : Type v) [has_sizeof α] [has_sizeof β] : has_sizeof (sum α β) :=
⟨sum.sizeof⟩
protected def sigma.sizeof {α : Type u} {β : α → Type v} [has_sizeof α] [∀ a, has_sizeof (β a)] : sigma β → nat
| ⟨a, b⟩ := 1 + sizeof a + sizeof b
instance (α : Type u) (β : α → Type v) [has_sizeof α] [∀ a, has_sizeof (β a)] : has_sizeof (sigma β) :=
⟨sigma.sizeof⟩
protected def unit.sizeof : unit → nat
| u := 1
instance : has_sizeof unit := ⟨unit.sizeof⟩
protected def punit.sizeof : punit → nat
| u := 1
instance : has_sizeof punit := ⟨punit.sizeof⟩
protected def bool.sizeof : bool → nat
| b := 1
instance : has_sizeof bool := ⟨bool.sizeof⟩
protected def pos_num.sizeof : pos_num → nat
| p := nat.of_pos_num p
instance : has_sizeof pos_num :=
⟨pos_num.sizeof⟩
protected def num.sizeof : num → nat
| n := nat.of_num n
instance : has_sizeof num :=
⟨num.sizeof⟩
protected def option.sizeof {α : Type u} [has_sizeof α] : option α → nat
| none := 1
| (some a) := 1 + sizeof a
instance (α : Type u) [has_sizeof α] : has_sizeof (option α) :=
⟨option.sizeof⟩
protected def list.sizeof {α : Type u} [has_sizeof α] : list α → nat
| list.nil := 1
| (list.cons a l) := 1 + sizeof a + list.sizeof l
instance (α : Type u) [has_sizeof α] : has_sizeof (list α) :=
⟨list.sizeof⟩
protected def subtype.sizeof {α : Type u} [has_sizeof α] {p : α → Prop} : subtype p → nat
| ⟨a, _⟩ := sizeof a
instance {α : Type u} [has_sizeof α] (p : α → Prop) : has_sizeof (subtype p) :=
⟨subtype.sizeof⟩
lemma nat_add_zero (n : nat) : n + 0 = n := rfl
/- Combinator calculus -/
namespace combinator
universes u₁ u₂ u₃
def I {α : Type u₁} (a : α) := a
def K {α : Type u₁} {β : Type u₂} (a : α) (b : β) := a
def S {α : Type u₁} {β : Type u₂} {γ : Type u₃} (x : α → β → γ) (y : α → β) (z : α) := x z (y z)
end combinator
/- Basic unification hints -/
@[unify] def add_succ_defeq_succ_add_hint (x y z : nat) : unification_hint :=
{ pattern := x + nat.succ y ≟ nat.succ z,
constraints := [z ≟ x + y] }