Lean 3 (archive)
Logic | Intro | Elim |
---|---|---|
\(\rightarrow\) | intro intros |
apply have h_3 := h_1 h_2 |
\(\forall\) | intro intros |
apply specialize have h_2 := h_1 t |
\(\exists\) | use |
cases |
\(\lnot\) | intro intros |
apply contradiction |
\(\land\) | split |
cases h.1 h.2 h.left h.right |
\(\leftrightarrow\) | split |
cases h.1 h.2 h.mp h.mpr rw |
\(\lor\) | left right |
cases |
\(\bot\) | N/A | contradiction ex_falso |
\(\top\) | trivial |
N/A |
Classical logic open_locale classical
use by_contradiction
tactic
Most of the time, implication and universal quantifier are treated the same.
1 rw
- given
h: a*b=b*a
rw h
means attempt to transform consequent usinga*b->b*a
⊢a*b+c
turns into⊢b*a+c
rw <- h
meansb*a->a*b
⊢b*a+c
turns into⊢a*b+c
1.1 Example
expected type:
abcd: ℝ
h₁: a ≤ b
h₂: c ≤ d
⊢ ∀ {α : Type u_1} {a b c d : α} [_inst_1 : preorder α]
[_inst_2 : has_add α]
[_inst_3 : covariant_class α α (function.swap has_add.add) has_le.le]
[_inst_4 : covariant_class α α has_add.add has_le.le]
, a ≤ b → c ≤ d → a + c ≤ b + d
Type
For any type α that has a pre order.
2 Types
if p : Prop
then
x:p
is a proof of proposition p : Prop
.
if y:p
is also a proof then proof irrelevance means x:p
and y:p
are indistinguishable.
- Props, terms
- Given \(P:Prop\) , the term \(h:P\) is a proof of \(P\)
- Implication \(P \rightarrow Q : Prop\) is the function type
- Given \(h1: P \rightarrow Q\) , \(h2:P\) conclude \(h1\ h2: Q\)
- Quantifier and Dependent Function type
- Given \(P:X \rightarrow Prop\) represents \(\forall( x: X). P\ x: Prop\)
3 Numbers
Proofs of numbers typically use type coercion.
norm_num
4 Inductive type
inductive mynat
| zero : mynat
| succ (n : mynat) : mynat
5 Definitional Equality and Reduction
- Given
- \(A \overset{reduces}{\rightarrow} X\)
- \(B \overset{reduces}{\rightarrow} X\)
- Implies
- \(A \underset{def}{\equiv} B\)
Conversion | Definition | Example |
---|---|---|
alpha | renaming | \(\lambda x. P x \equiv \lambda y. P y\) |
beta | computing | \((\lambda x. x + 2) 3 \equiv 3 + 2\) |
6 Dependent type
6.1 Inspiring the dependent type
cons 2 [3,4] : List Nat
cons : Nat -> List Nat -> List Nat
What if we wanted a polymorphic cons
?
Give first argument as the Type
cons Nat 2 [3,4] : Type -> T -> List T -> List T
- Nat : Type
- 2 : T
- [3,4] : List T
Notice T
= Nat
We need T
in Type-Space to relate to Nat
in Term-Space. How?
Abstract away the term Nat
to a bound term variable Π T
Type -> T -> List T -> List T
=>
Π T : Type -> T -> List T -> List T
namespace hidden
universe u
constant list : Type u → Type u
constant cons : Π α : Type u, α → list α → list α
constant nil : Π α : Type u, list α
constant head : Π α : Type u, list α → α
constant tail : Π α : Type u, list α → list α
constant append : Π α : Type u, list α → list α → list α
#check cons α a (nil α)
end hidden
Observe how we can use Dependent Product Type for polymorphism.
\[\prod_{x: \alpha} \beta = \prod_{x: \alpha} (x \rightarrow list\ x \rightarrow list\ x)\]
Pi-type or dependent product type behaves like lambda in the type space
β is an EXPRESSION that can be expanded.
β may or may not include bound variable x in it’s expression
cons :: Π x : α, β
What is the type of cons int
?
We apply (Π x : α, β)
to int
in the type space.
cons int :: (Π x : α, β)(int)
(Π x : α, β)(int)
- Beta-reduction:
β[int/x]
β
expanded isx -> list x -> list x
β[int/x]
is(x -> list x -> list x)[int/x]
- replace x with int resulting in
(int -> list int -> list int)
cons int :: (Π x : α, β)(int)
is
cons int :: int -> list int -> list int
Example of a list is cons int 3 (nil int)
Since cons
and nil
are dependent types, they must take an extra parameter [in this case] int
f :: Π x : α, β
= f x :: β[x]
where x :: α
6.1.1 function type is just a Pi-type
when
β
expanded expression does not include
bound variableΠ x : α
then
β[x]
=β
example:
f :: Π x : α, β
= f x :: β[x]
= f x :: β
= f :: α -> β
example β
is bool
, α
is nat
Notice bool
is an expression that does not include any bound variable x:nat
even :: Π x : α, β
even :: Π x : nat, bool
even :: nat -> bool
6.2 Sigma Type
: Type) (β : α → Type) (a : α) (b : β a) : (a : α) × β a :=
def f (α
⟨a, b⟩: Nat) : Nat :=
def h1 (x Type (fun p => p) Nat x).2
(f
-- (α : Type) is (Type : Type)
-- β is (fun p => p : Type -> Type)
-- (a : α) is (Nat : Type)
-- (b : β a) is (x : (fun p => p)(Nat)) which is (x : Nat)
How to look at f
? Extract the types
Type -> (α → Type) -> α -> β a -> ((a : α) × β a)
7 Notation
7.1 Curly vs Smooth Parenthesis
- Curly
{a: Type u}
stands for notational shortcuts aka implicit arguments that do not need to be written - Smooth
(a: Type u)
stands for explicit aka we need to write out the type as an argument
---- Curly vs Bracket
---- {a: Type u} vs (a: Type u)
---- implicit argument vs explicit
--They mean the same but implicit argument allows us to omit arguments for shorter declarations.
--implicit argument means that {a: Type u} will get autofilled
-- ex1: "nil nat" becomes "nil", the "nat" is the implicit argument that gets autofilled
-- ex2: "cons nat 4 (nil nat)" becomes "cons 4 nil", here we see {a: Type u} is "nat"
--
: list nat
variables p
universe u--implicit arguments are just notation shortcuts
: Type u } : a -> list a -> list a
constant consImplicit {a : Π {a : Type u}, list a
constant nilImplicit #check consImplicit --?M_1 → list ?M_1 → list ?M_1
--consA shows metavar like ?M_1
--using @ fills in the metavar with types
#check @consImplicit
#check nilImplicit
#check consImplicit 4 nilImplicit
--explicit arguments
: Type u) : a -> list a -> list a
constant consExplicit (a
: Π (a : Type u), list a
constant nilExplicit #check consExplicit
#check consExplicit
#check consExplicit 4 nilExplicit --error
#check consExplicit 4 nilExplicit --error
#check consExplicit nat 4 (nilExplicit nat) --ok
7.2 Pi-type, forall, parenthesis
-- notice that we Pi-type == forall or we can push the quantifier into a parenthesis.
-- three cons below are the same.
: Πa : Type u , a -> list a -> list a
constant consA : ∀a : Type u , a -> list a -> list a
constant consB : ∀(a : Type u), a -> list a -> list a
constant consC : Π(a : Type u) , a -> list a -> list a
constant consD : Type u) : a -> list a -> list a constant consE (a
8 Simple interpreter
section basiclang
Term : Type
inductive | T : Term
| F : Term
| O : Term
| IfThenElse : Term -> Term -> Term -> Term
| S : Term -> Term
| P : Term -> Term
| IsZero : Term -> Term
Term
open
: Term -> Term
def eval | (IfThenElse T s2 s3) := s2
| (IfThenElse F s2 s3) := s3
| (IfThenElse s1 s2 s3) :=
let ns1 := eval s1 in (IfThenElse ns1 s1 s2)
| (S s1) :=
let ns1 := eval s1 in (S ns1)
| (P O) := O
| (P (S k)) := k
| (P s1) :=
let ns1 := eval s1 in (P ns1)
| (IsZero O) := T
| (IsZero (S k)) := F
| (IsZero s1) :=
let ns1 := eval s1 in (IsZero ns1)
| _ := F
#reduce eval $ P $ S $ P O
#reduce eval $ IsZero O
#reduce eval $ IfThenElse (IsZero O) (S O) (S $ S O)
--- s1 -> ns1
--- ---------------
--- S s1 -> S ns1
ToNat : Term -> nat
def | O := 0
| (S (n: Term)) := 1 + ToNat n
| _ := 1
#reduce ToNat (eval $ S $ S $ S $ O)
end basiclang
--extensionality vs intensionality
--extensionality means functions that behave the same are the same
--intensionality means functions that behave the same but built differently are not the same
: ℕ → ℕ → ℕ
def foo | 0 n := 0
| (m+1) 0 := 1
| (m+1) (n+1) := 2
#reduce foo 5 0
Combinators
section
I {a : Type*} : a -> a := λx , x
def K {a b: Type*} : a -> b -> a := λx , λy, x
def : Type*} : (a -> b) -> a -> b := λf, λx, f x
def app {a bS {a b c: Type*} : (a -> b -> c) -> (a -> b) -> a -> c := λf, λg, λa , f a (g a)
def
#eval I 2
#check S K S K
#check K K (S K)
#check (S I I)
Combinators
end
#reduce (λx, x + 2)5
9 Understanding Coq
What below means is that pairn :: nat -> nat -> natprod
aka pairn (n1 n2) :: natprod
* correct version *)
(Inductive natprod : Type :=
| pairn (n1 n2 : nat).
What below means is that pairn :: Π(na : nat) -> Πi(nb : nat) -> nat -> nat -> natprod na nb
Inductive natprod (na nb : nat): Type :=
| pairn (n1 n2 : nat).
- Inductive is not Definition
Inductive bleh (one : Type a) : Type := ...
Definition bleh (one: Type a) : Type := ...