Empty and Unit types
In this chapter, we explore two of the simplest—but most fundamental—types in Lean: the Empty
type and the Unit
type. Though these types may seem trivial at first glance, they play a crucial role in the logic and structure of formal proofs.
Empty
The Empty type, written as Empty
, is a type with no inhabitants.
If we #print Empty
, Lean returns:
This means that if we have a value of type Empty
, we can derive a value of any other type from it. In Lean, this is done using the Empty.elim
function, which expresses the logical principle that from falsehood, anything follows.
An interesting property of the emptyToAny
function is that it is unique up to definitional equality; any two functions with type Empty → A
are definitionally the same.
emptyToAny
This implies that the emptyToAny
function with codomain Empty
is, in particular, the identity function on Empty
.
Unit
The Unit type, written as Unit
, is a type with exactly one inhabitant: Unit.unit
, usually just written ()
.
If we #print Unit
, Lean returns:
There is always a function from any type to the Unit
type, since we can simply ignore the input and return ()
.
The anyToUnit
function is unique up to definitional equality; any two functions with type A → Unit
are definitionally the same.
This implies that when the domain is Unit
, the anyToUnit
function is, in particular, the identity function on Unit
.
Exercises
Empty
Exercises.lean
-- All the elements of `Empty` are equal
theorem emptyUnique : ∀ (x y : Empty), x = y := by sorry
-- The `emptyToAny` function is injective
theorem emptyToAnyInj {A : Type} : injective (@emptyToAny A) := by sorry
-- Under `Classical.choice`, if the `emptyToAny` function is surjective, the codomain cannot be `Nonempty`
theorem emptyToAnySurj {A : Type} : surjective (@emptyToAny A) ↔ ¬ (Nonempty A) := by sorry
Unit
Exercises.lean
-- All the elements of `Unit` are equal
theorem unitUnique : ∀ (x y : Unit), x = y := by sorry
-- The `anyToUnit` function is injective if, and only if, the domain has only one element
theorem anyToUnitInj {A : Type} : injective (@anyToUnit A) ↔ (∀ (a1 a2 : A), a1 = a2) := by sorry
-- Under `Classical.choice`, the `anyToUnit` function is surjective if and only if the domain is `Nonempty`
theorem anyToUnitSurj {A : Type} : surjective (@anyToUnit A) ↔ Nonempty A := by sorry