module Padova2025.Cubical.Issues.FunctionExtensionality where
Function extensionality
open import Padova2025.ProgrammingBasics.Booleans open import Padova2025.ProgrammingBasics.Naturals.Base open import Padova2025.ProvingBasics.Equality.Base open import Padova2025.ProvingBasics.Equality.General
Let us consider the following three function definitions.
example₁ : Bool → Bool example₁ x = x example₂ : Bool → Bool example₂ false = false example₂ true = true example₃ : Bool → Bool example₃ false = false example₃ true = true -- Yes, identical to the definition of example₂.
Obviously, these functions have the same values on all inputs:
all-same₁₂ : (x : Bool) → example₁ x ≡ example₂ x all-same₁₂ false = refl all-same₁₂ true = refl all-same₂₃ : (x : Bool) → example₂ x ≡ example₃ x all-same₂₃ false = refl all-same₂₃ true = refl
Not provably the same. However, in standard Agda we
can not prove that the functions themselves are the same—the following
holes cannot be filled (and the proposal refl
does not
typecheck):
_ : example₁ ≡ example₂
_ = ?
_ : example₂ ≡ example₃
_ = ?
Not provably distinct. On the other hand, in Agda we
can also not prove the three functions above to be distinct, that is we
cannot write down terms of type exampleᵢ ≡ exampleⱼ → ⊥
.
Agda is (like any other reasonable formal system) incomplete. This
particular instance of incompleteness is particularly worrying to some,
as it pertains to such a basic part of Agda. The equality type is
underspecified.
A principle. The principle that functions with equal values are themselves equal is known as function extensionality. Blackboard mathematics has it, while standard Agda does not.
FunctionExtensionality : Set₁ FunctionExtensionality = {X Y : Set} {f g : X → Y} → ((x : X) → f x ≡ g x) → f ≡ g
Postulating function extensionality
We may, if we prefer, postulate function extensionality:
postulate
funext : FunctionExtensionality
Adding function extensionality to Martin-Löf type theory preserves its consistency. Moreover, if one entertains the idea of a platonic heaven, then one can rest assured that the resulting type theory still provides an apt language for talking about the objects of the platonic heaven.
However, by postulating function extensionality we lose
canonicity: With this postulate, it can happen that elements of
inductively defined types do not reduce to a constructor call. A basic
example is already provided by funext
itself.
does-not-reduce-to-refl : example₁ ≡ example₂
does-not-reduce-to-refl = funext all-same₁₂
does-not-reduce-to-a-numeral : ℕ
does-not-reduce-to-a-numeral = check does-not-reduce-to-refl
where
check : {g : Bool → Bool} → example₁ ≡ g → ℕ
check refl = zero
Avoiding function extensionality
For many purposes, function extensionality can easily be avoided by
employing pointwise
equality instead of true _≡_
, as follows.
all-same₁₂' : example₁ ≗ example₂ all-same₁₂' = all-same₁₂
But it is also desireable to actually have function extensionality. Such a system is offered by Cubical Agda.
Exercise: Pointwise equality is an equivalence relation
≗-refl : {X Y : Set} {f : X → Y} → f ≗ f ≗-refl = {!!}
≗-sym : {X Y : Set} {f g : X → Y} → f ≗ g → g ≗ f ≗-sym = {!!}
≗-trans : {X Y : Set} {f g h : X → Y} → f ≗ g → g ≗ h → f ≗ h ≗-trans = {!!}
Exercise: Types form a category
Let f
, g
and h
be composable
functions. Then we definitely have
(h ∘ g) ∘ f ≗ h ∘ (g ∘ f)
. Does the same identity also hold
with _≡_
in place of _≗_
, or is function
extensionality needed for that?
open import Padova2025.ProgrammingBasics.HigherOrder open import Padova2025.ProgrammingBasics.DependentFunctions
Even though standard Agda does not have function extensionality, it
does have eta equality: Every function f
is
judgmentally equal to the lambda λ x → f x
. This principle
is enough to verify that the (small) types form a category, up to true
propositional equality and not only up to pointwise equality.
∘-assoc : {X Y Z W : Set} → (f : X → Y) (g : Y → Z) (h : Z → W) → (h ∘ g) ∘ f ≡ h ∘ (g ∘ f) ∘-assoc = {!!}
∘-identityˡ : {X Y : Set} → (f : X → Y) → id Y ∘ f ≡ f ∘-identityˡ = {!!}
∘-identityʳ : {X Y : Set} → (f : X → Y) → f ∘ id X ≡ f ∘-identityʳ = {!!}
Having established that types form a category, a category theorist might enquire about its categorical properties. For instance, in blackboard mathematics, the category Set has an initial object, namely the empty set ∅: For every set X, there is exactly one map ∅ → X.
Does the category of types have an initial object? How about a terminal object?
No initial object
Agda does have the empty type ⊥
, and for every type
X
there is a map ⊥-elim : ⊥ → X
.
Hence the category of types has a weakly initial object.
However, without function extensionality, we cannot show that any two
functions of type ⊥ → X
are identical.
Terminal object
On the other hand, there is a terminal object. This is provided by the following declaration.
record 𝟙 : Set where constructor tt
Record types by default have (their own version of) eta equality. That is the reason why any two inhabitants are judgmentally equal:
_ : (x y : 𝟙) → x ≡ y _ = λ x y → refl
As a corollary, any two functions to 𝟙
are judgmentally
equal:
_ : {X : Set} → {f g : X → 𝟙} → f ≡ g _ = refl
In constract, declaring 𝟙
as an ordinary inductive
datatype (or disabling eta equality with the
no-eta-equality
keyword in the record declaraction) will
provide us with a type in which any two inhabitants are propositionally
but not judgmentally equal.
data 𝟙' : Set where tt : 𝟙' 𝟙'-isProp : (x y : 𝟙') → x ≡ y 𝟙'-isProp tt tt = refl -- But without the pattern match, 𝟙'-isProp x y = refl, there is a type error.
Category of setoids
Even though the category of types is perhaps the first to reach out to when exploring the landscape of categories in Agda, the category of (small) setoids is for many applications actually much more sensible, less dependent on foundations (such as the availability or non-availability of function extensionality) and also much better behaved. For instance, the category of setoids is complete and cocomplete, locally cartesian closed, exact and extensive. It also validates a version of the axiom of choice. All of these assertions can be explored in great detail in the categories library in the module Categories.Category.Instance.Properties.Setoids and its submodules.