There were two performance bottlenecks in the recursive equation
compiler. Both bottlenecks were due to conversion checking.
1- We allow patterns such as (x+1) in the left-hand-side of a
recursive equation. This is kind of pattern has to be reduced
since it is not a constructor. Moreover, when we are trying to
compile using structural recursion, we need to find an element
that is structurally smaller in recursive applications.
Again, we need to use reduction since the pattern may be (x+2),
and in the recursive application we have (x+1). Now, consider
the following equation
f (x+1) (y+1) := f complex_term y
It will first check whether complex_term is structurally smaller
than (x+1), and the compiler will timeout trying to reduce
complex_term.
This commit adds the following workaround. The structural
recursion module from now on will only unfold reducible constants
and constants marked as patterns. This is not a complete
solution. It will timeout in the following equation:
f (x+1) (y+1) := f (x+1000000000000) y
For this one, we need to add a whnf "fuel" option to type_context
2- Equational lemma generation was producing lemmas that are too
expensive to check. Suppose we the following two definitions
| f x 0 := 1
| f x (y+1) := f complex_term y
and
| g 0 y := 1
| g (x+1) y := g x complex_term
Before this commit, we would generate the following proofs for
the second equation of each definition:
eq.refl (f complex_term y)
eq.refl (g x complex_term)
This proof triggers the following definitionally equality test:
f x (y+1) =?= f complex_term y
g (x+1) y =?= g x complex_term
Since, we have f/g on both sides, the type checker will try
first to unify the arguments, and may timeout trying to solve
x =?= complex_term
y =?= complex_term
since it may take a long time to reduce `complex_term`.
We workaround this problem by creating a slightly different
proof.
eq.refl (unfold_of(f x (y+1)))
eq.refl (unfold_of(g (x+1) y))
where unfold_of(t) is the result of applying one delta reduction
step.
614 lines
18 KiB
Text
614 lines
18 KiB
Text
/-
|
||
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
|
||
|
||
/- 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
|
||
|
||
/-- 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 := α
|
||
|
||
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
|
||
|
||
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) :=
|
||
tag :: (elt_of : α) (has_property : p elt_of)
|
||
|
||
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
|
||
|
||
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 (α : out_param (Type u)) (γ : Type v) := (insert : α → γ → γ)
|
||
/- Type class used to implement the notation { a ∈ c | p a } -/
|
||
class has_sep (α : out_param (Type u)) (γ : Type v) :=
|
||
(sep : (α → Prop) → γ → γ)
|
||
/- Type class for set-like membership -/
|
||
class has_mem (α : out_param (Type u)) (γ : Type v) := (mem : α → γ → Prop)
|
||
|
||
def zero {α : Type u} [has_zero α] : α := has_zero.zero α
|
||
def one {α : Type u} [has_one α] : α := has_one.one α
|
||
def add {α : Type u} [has_add α] : α → α → α := has_add.add
|
||
def mul {α : Type u} [has_mul α] : α → α → α := has_mul.mul
|
||
def sub {α : Type u} [has_sub α] : α → α → α := has_sub.sub
|
||
def div {α : Type u} [has_div α] : α → α → α := has_div.div
|
||
def dvd {α : Type u} [has_dvd α] : α → α → Prop := has_dvd.dvd
|
||
def mod {α : Type u} [has_mod α] : α → α → α := has_mod.mod
|
||
def neg {α : Type u} [has_neg α] : α → α := has_neg.neg
|
||
def inv {α : Type u} [has_inv α] : α → α := has_inv.inv
|
||
def le {α : Type u} [has_le α] : α → α → Prop := has_le.le
|
||
def lt {α : Type u} [has_lt α] : α → α → Prop := has_lt.lt
|
||
def append {α : Type u} [has_append α] : α → α → α := has_append.append
|
||
def andthen {α : Type u} [has_andthen α] : α → α → α := has_andthen.andthen
|
||
def union {α : Type u} [has_union α] : α → α → α := has_union.union
|
||
def inter {α : Type u} [has_inter α] : α → α → α := has_inter.inter
|
||
def sdiff {α : Type u} [has_sdiff α] : α → α → α := has_sdiff.sdiff
|
||
def subset {α : Type u} [has_subset α] : α → α → Prop := has_subset.subset
|
||
def ssubset {α : Type u} [has_ssubset α] : α → α → Prop := has_ssubset.ssubset
|
||
@[reducible]
|
||
def ge {α : Type u} [has_le α] (a b : α) : Prop := le b a
|
||
@[reducible]
|
||
def gt {α : Type u} [has_lt α] (a b : α) : Prop := lt b a
|
||
@[reducible]
|
||
def superset {α : Type u} [has_subset α] (a b : α) : Prop := subset b a
|
||
@[reducible]
|
||
def ssuperset {α : Type u} [has_ssubset α] (a b : α) : Prop := ssubset b a
|
||
def bit0 {α : Type u} [s : has_add α] (a : α) : α := add a a
|
||
def bit1 {α : Type u} [s₁ : has_one α] [s₂ : has_add α] (a : α) : α := add (bit0 a) one
|
||
|
||
attribute [pattern] zero one bit0 bit1 add neg
|
||
|
||
def insert {α : Type u} {γ : Type v} [has_insert α γ] : α → γ → γ :=
|
||
has_insert.insert
|
||
|
||
/- The empty collection -/
|
||
def emptyc {α : Type u} [has_emptyc α] : α :=
|
||
has_emptyc.emptyc α
|
||
|
||
def singleton {α : Type u} {γ : Type v} [has_emptyc γ] [has_insert α γ] (a : α) : γ :=
|
||
insert a emptyc
|
||
|
||
def sep {α : Type u} {γ : Type v} [has_sep α γ] : (α → Prop) → γ → γ :=
|
||
has_sep.sep
|
||
|
||
def mem {α : Type u} {γ : Type v} [has_mem α γ] : α → γ → Prop :=
|
||
has_mem.mem
|
||
|
||
/- 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
|
||
|
||
infix = := eq
|
||
infix == := heq
|
||
infix ∈ := mem
|
||
notation a ∉ s := ¬ mem a s
|
||
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
|
||
notation `∅` := emptyc
|
||
infix ∪ := union
|
||
infix ∩ := inter
|
||
infix ⊆ := subset
|
||
infix ⊇ := superset
|
||
infix ⊂ := ssubset
|
||
infix ⊃ := ssuperset
|
||
infix \ := sdiff
|
||
|
||
notation α × β := prod α β
|
||
-- notation for n-ary tuples
|
||
notation `(` h `, ` t:(foldr `, ` (e r, prod.mk e r)) `)` := prod.mk h t
|
||
|
||
/- eq basic support -/
|
||
|
||
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
|
||
|
||
/- 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 `α` -/
|
||
instance default_has_sizeof (α : Sort u) : has_sizeof α :=
|
||
⟨λ a, nat.zero⟩
|
||
|
||
/- TODO(Leo): the [simp.sizeof] annotations are not really necessary.
|
||
What we need is a robust way of unfolding sizeof definitions. -/
|
||
attribute [simp.sizeof]
|
||
lemma default_has_sizeof_eq (α : Sort u) (a : α) : @sizeof α (default_has_sizeof α) a = 0 :=
|
||
rfl
|
||
|
||
instance : has_sizeof nat :=
|
||
⟨λ a, a⟩
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_nat_eq (a : nat) : sizeof a = a :=
|
||
rfl
|
||
|
||
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⟩
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_prod_eq {α : Type u} {β : Type v} [has_sizeof α] [has_sizeof β] (a : α) (b : β) : sizeof (prod.mk a b) = 1 + sizeof a + sizeof b :=
|
||
rfl
|
||
|
||
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⟩
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_sum_eq_left {α : Type u} {β : Type v} [has_sizeof α] [has_sizeof β] (a : α) : sizeof (@sum.inl α β a) = 1 + sizeof a :=
|
||
rfl
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_sum_eq_right {α : Type u} {β : Type v} [has_sizeof α] [has_sizeof β] (b : β) : sizeof (@sum.inr α β b) = 1 + sizeof b :=
|
||
rfl
|
||
|
||
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⟩
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_sigma_eq {α : Type u} {β : α → Type v} [has_sizeof α] [∀ a, has_sizeof (β a)] (a : α) (b : β a) : sizeof (@sigma.mk α β a b) = 1 + sizeof a + sizeof b :=
|
||
rfl
|
||
|
||
instance : has_sizeof unit := ⟨λ u, 1⟩
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_unit_eq (u : unit) : sizeof u = 1 :=
|
||
rfl
|
||
|
||
instance : has_sizeof punit := ⟨λ u, 1⟩
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_punit_eq (u : punit) : sizeof u = 1 :=
|
||
rfl
|
||
|
||
instance : has_sizeof bool := ⟨λ u, 1⟩
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_bool_eq (b : bool) : sizeof b = 1 :=
|
||
rfl
|
||
|
||
instance : has_sizeof pos_num :=
|
||
⟨nat.of_pos_num⟩
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_pos_num_eq (p : pos_num) : sizeof p = nat.of_pos_num p :=
|
||
rfl
|
||
|
||
instance : has_sizeof num :=
|
||
⟨nat.of_num⟩
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_num_eq (n : num) : sizeof n = nat.of_num n :=
|
||
rfl
|
||
|
||
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⟩
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_option_none_eq (α : Type u) [has_sizeof α] : sizeof (@none α) = 1 :=
|
||
rfl
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_option_some_eq {α : Type u} [has_sizeof α] (a : α) : sizeof (some a) = 1 + sizeof a :=
|
||
rfl
|
||
|
||
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⟩
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_list_nil_eq (α : Type u) [has_sizeof α] : sizeof (@list.nil α) = 1 :=
|
||
rfl
|
||
|
||
attribute [simp.sizeof]
|
||
lemma sizeof_list_cons_eq {α : Type u} [has_sizeof α] (a : α) (l : list α) : sizeof (list.cons a l) = 1 + sizeof a + sizeof l :=
|
||
rfl
|
||
|
||
attribute [simp.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
|