Built with doc-gen4, running Lean4. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑Ctrl+↓to navigate, Ctrl+🖱️to focus. On Mac, use Cmdinstead of Ctrl.
```import Mathlib

/-!
# Propositions as Types

* We can represent propositions as types, or interpret (slightly restricted) types as propositions.
* A proof of a proposition is a term of the corresponding type.
* Defining and proving are essentially the same thing.
* The same foundational rules let us construct propostions and proofs as well as terms and types.
-/

/-!
## Main correspondence

* `A → B` is functions from `A` to `B` as well as `A` implies `B`.
* Function application is the same as *modus ponens*.
* So if we have propositions `A` and `B`, we can construct a proposition `A → B` corresponding to implication.
-/

universe u

def functionApplication: {A B : Type u} → (A → B) → A → BfunctionApplication {A: Type uA B: Type uB : Type u: Type (u+1)Type u} (f: A → Bf : A: Type uA → B: Type uB) (a: Aa : A: Type uA) : B: Type uB := f: A → Bf a: Aa

def modus_ponens: ∀ {A B : Prop}, (A → B) → A → Bmodus_ponens {A: PropA B: PropB : Prop: TypeProp} (h₁: A → Bh₁ : A: PropA → B: PropB) (h₂: Ah₂ : A: PropA) : B: PropB := h₁: A → Bh₁ h₂: Ah₂

/-!
## Other Combination

* `A ∧ B` is the conjunction of `A` and `B`.
* `A ∨ B` is the disjunction of `A` and `B`.
* `¬ A` is the negation of `A`.

All these can be constructed by our rules.

-/

#checkAnd (a b : Prop) : Prop And: Prop → Prop → PropAnd
#checkProd.{u, v} (α : Type u) (β : Type v) : Type (max u v) Prod: Type u → Type v → Type (maxuv)Prod

/-!
## Conjuction and Product

```lean
structure And (a b : Prop) : Prop where
/-- `And.intro : a → b → a ∧ b` is the constructor for the And operation. -/
intro ::
/-- Extract the left conjunct from a conjunction. `h : a ∧ b` then
`h.left`, also notated as `h.1`, is a proof of `a`. -/
left : a
/-- Extract the right conjunct from a conjunction. `h : a ∧ b` then
`h.right`, also notated as `h.2`, is a proof of `b`. -/
right : b
```

This is the same as the product type:

```lean
structure Prod (α : Type u) (β : Type v) where
/-- The first projection out of a pair. if `p : α × β` then `p.1 : α`. -/
fst : α
/-- The second projection out of a pair. if `p : α × β` then `p.2 : β`. -/
snd : β
```
-/

inductive MyOr: Prop → Prop → PropMyOr (A: PropA B: PropB : Prop: TypeProp) : Prop: TypeProp
| inl: ∀ {A B : Prop}, A → MyOr A Binl : A: PropA → MyOr: Prop → Prop → PropMyOr A: PropA B: PropB
| inr: ∀ {A B : Prop}, B → MyOr A Binr : B: PropB → MyOr: Prop → Prop → PropMyOr A: PropA B: PropB

#checkOr (a b : Prop) : Prop Or: Prop → Prop → PropOr
#checkSum.{u, v} (α : Type u) (β : Type v) : Type (max u v) Sum: Type u → Type v → Type (maxuv)Sum

/-!
# Disjunction and Sum

```lean
inductive Or (a b : Prop) : Prop where
/-- `Or.inl` is "left injection" into an `Or`. If `h : a` then `Or.inl h : a ∨ b`. -/
| inl (h : a) : Or a b
/-- `Or.inr` is "right injection" into an `Or`. If `h : b` then `Or.inr h : a ∨ b`. -/
| inr (h : b) : Or a b
```

This is the same as the sum type:

```lean
inductive Sum (α : Type u) (β : Type v) where
/-- Left injection into the sum type `α ⊕ β`. If `a : α` then `.inl a : α ⊕ β`. -/
| inl (val : α) : Sum α β
/-- Right injection into the sum type `α ⊕ β`. If `b : β` then `.inr b : α ⊕ β`. -/
| inr (val : β) : Sum α β
```
-/

#checkTrue : Prop True: PropTrue
#checkFalse : Prop False: PropFalse

/-!
## True and False

These are analogues of `Unit` and `Empty`:

```lean
inductive True : Prop where
/-- `True` is true, and `True.intro` (or more commonly, `trivial`)
is the proof. -/
| intro : True

inductive False : Prop
```
-/

/-!
## Negation

The negation of a type (or proposition) `A` is `¬ A`, which is the type (or proposition) `A → False`.

-/

theorem everything_implies_true: ∀ (A : Prop), A → Trueeverything_implies_true (A: PropA : Prop: TypeProp) : A: PropA → True: PropTrue := fun _: ?m.171_ => True.intro: TrueTrue.intro

theorem false_implies_everything: ∀ (A : Prop), False → Afalse_implies_everything (A: PropA : Prop: TypeProp) : False: PropFalse → A: PropA := fun h: ?m.184h => nomatch h: ?m.184h

#checkFalse.rec.{u} (motive : False → Sort u) (t : False) : motive t False.rec: (motive : False → Sort u) → (t : False) → motive tFalse.rec -- False.rec.{u} (motive : False → Sort u) (t : False) : motive t

#checkFalse.rec fun x => 1 = 2 : False → 1 = 2 False.rec: ∀ (motive : False → Sort ?u.214) (t : False), motive tFalse.rec (motive := fun _: ?m.221_ => 1: ?m.2251 = 2: ?m.2412) -- False → 1 = 2

example: ∀ {A B : Prop}, A → B → Aexample {A: PropA B: PropB : Prop: TypeProp}: A: PropA → B: PropB → A: PropA :=
fun a: ?m.324a _: ?m.327_ ↦ a: ?m.324a

#checkIff (a b : Prop) : Prop Iff: Prop → Prop → PropIff

/-!
## If and only if

```lean
structure Iff (a b : Prop) : Prop where
/-- If `a → b` and `b → a` then `a` and `b` are equivalent. -/
intro ::
/-- Modus ponens for if and only if. If `a ↔ b` and `a`, then `b`. -/
mp : a → b
/-- Modus ponens for if and only if, reversed. If `a ↔ b` and `b`, then `a`. -/
mpr : b → a
```
-/

example: ∀ {A B : Prop}, (A ↔ B) = ((A → B) ∧ (B → A))example {A: PropA B: PropB : Prop: TypeProp}: (A: PropA ↔  B: PropB) =
((A: PropA → B: PropB) ∧ (B: PropB → A: PropA)) := byGoals accomplished! 🐙
A, B: Prop(A ↔ B) = ((A → B) ∧ (B → A))apply propext: ∀ {a b : Prop}, (a ↔ b) → a = bpropextA, B: Propa(A ↔ B) ↔ (A → B) ∧ (B → A)
A, B: Prop(A ↔ B) = ((A → B) ∧ (B → A))apply Iff.intro: ∀ {a b : Prop}, (a → b) → (b → a) → (a ↔ b)Iff.introA, B: Propa.mp(A ↔ B) → (A → B) ∧ (B → A)A, B: Propa.mpr(A → B) ∧ (B → A) → (A ↔ B)
A, B: Prop(A ↔ B) = ((A → B) ∧ (B → A))case a.mp =>
A, B: Prop(A ↔ B) → (A → B) ∧ (B → A)intro h: ?ahA, B: Proph: A ↔ B(A → B) ∧ (B → A)
A, B: Prop(A ↔ B) → (A → B) ∧ (B → A)apply And.intro: ∀ {a b : Prop}, a → b → a ∧ bAnd.introA, B: Proph: A ↔ BleftA → BA, B: Proph: A ↔ BrightB → A
A, B: Prop(A ↔ B) → (A → B) ∧ (B → A)· A, B: Proph: A ↔ BleftA → BA, B: Proph: A ↔ BrightB → Aexact h: ?ah.mp: ∀ {a b : Prop}, (a ↔ b) → a → bmpGoals accomplished! 🐙
A, B: Prop(A ↔ B) → (A → B) ∧ (B → A)· A, B: Proph: A ↔ BrightB → Aexact h: ?ah.mpr: ∀ {a b : Prop}, (a ↔ b) → b → amprGoals accomplished! 🐙
A, B: Prop(A ↔ B) = ((A → B) ∧ (B → A))case a.mpr =>
A, B: Prop(A → B) ∧ (B → A) → (A ↔ B)intro h: ?bhA, B: Proph: (A → B) ∧ (B → A)A ↔ B
A, B: Prop(A → B) ∧ (B → A) → (A ↔ B)apply Iff.intro: ∀ {a b : Prop}, (a → b) → (b → a) → (a ↔ b)Iff.introA, B: Proph: (A → B) ∧ (B → A)mpA → BA, B: Proph: (A → B) ∧ (B → A)mprB → A
A, B: Prop(A → B) ∧ (B → A) → (A ↔ B)· A, B: Proph: (A → B) ∧ (B → A)mpA → BA, B: Proph: (A → B) ∧ (B → A)mprB → Aexact h: ?bh.left: ∀ {a b : Prop}, a ∧ b → aleftGoals accomplished! 🐙
A, B: Prop(A → B) ∧ (B → A) → (A ↔ B)· A, B: Proph: (A → B) ∧ (B → A)mprB → Aexact h: ?bh.right: ∀ {a b : Prop}, a ∧ b → brightGoals accomplished! 🐙

/-!
## Universal Quantifiers

* A proposition associated to each term of a type `A` is a function `A → Prop`.
* The propostion `∀ x : A, P x` is the proposition that `P x` is true for all `x : A`, which is the dependent function type
`(x: A) → P x`.

-/

#checkExists.{u} {α : Sort u} (p : α → Prop) : Prop Exists: {α : Sort u} → (α → Prop) → PropExists

/-!
## Existential Quantifiers

```lean
inductive Exists {α : Sort u} (p : α → Prop) : Prop where
/-- Existential introduction. If `a : α` and `h : p a`,
then `⟨a, h⟩` is a proof that `∃ x : α, p x`. -/
| intro (w : α) (h : p w) : Exists p
```
-/

#checkNat.le (n a✝ : ℕ) : Prop Nat.le: ℕ → ℕ → PropNat.le
#checkEq.{u_1} {α : Sort u_1} (a✝a✝¹ : α) : Prop Eq: {α : Sort u_1} → α → α → PropEq

/-!
## Basic types

We have seen `≤` can be constructed as indexed inductive type:

```lean
inductive Nat.le (n : Nat) : Nat → Prop
/-- Less-equal is reflexive: `n ≤ n` -/
| refl     : Nat.le n n
/-- If `n ≤ m`, then `n ≤ m + 1`. -/
| step {m} : Nat.le n m → Nat.le n (succ m)
```

The equality type is also indexed inductive type:

```lean
inductive Eq : α → α → Prop where
/-- `Eq.refl a : a = a` is reflexivity, the unique constructor of the