Examples.FunctionTypeBijections¶
N-ary function encodings¶
This is the Examples.FunctionTypeBijections module of the Agda Universal Algebra Library.
This module is illustrative rather than load-bearing. It investigates three competing encodings of n-ary functions on a type — the curried form A → A → B, the product form A × A → B, and the Fin-indexed form (Fin n → A) → B — and surfaces a subtle phenomenon: while A × A → B and A → A → B are bijective up to definitional equality (Curry and Uncurry are mutually inverse on the nose), the Fin-indexed encoding does not enjoy a definitional bijection with either of the other two. The obstruction is η-expansion failure for function types out of Fin n: the equation (λ {z → u z; (s z) → u (s z)}) ≈ u holds only pointwise, not definitionally.
This phenomenon is directly relevant to the universal-algebra core, where n-ary operations are encoded as (Fin n → A) → A. Algebraists who reach for the "obvious" curried form A → ⋯ → A → A and expect to recover the canonical encoding by refl will find this module a useful cautionary example.
The content was relocated here under #310 from Legacy.Base.Functions.Transformers; nothing in the canonical Setoid/, Classical/, or planned Cubical/ development of the library depends on it.
Bijections of nondependent function types¶
The first piece of infrastructure is the type of bijections between two types, in two flavors: the definitional flavor (Bijection, where the round-trip composites are required to be _≡_-equal to id) and the pointwise flavor (PointwiseBijection, where pointwise equality _≈_ suffices). The investigation below turns on the gap between these two notions.
record Bijection (A : Type a)(B : Type b) : Type (a ⊔ b) where field to : A → B from : B → A to-from : to ∘ from ≡ id from-to : from ∘ to ≡ id ∣_∣=∣_∣ : (A : Type a)(B : Type b) → Type (a ⊔ b) ∣ A ∣=∣ B ∣ = Bijection A B record PointwiseBijection (A : Type a)(B : Type b) : Type (a ⊔ b) where field to : A → B from : B → A to-from : to ∘ from ≈ id from-to : from ∘ to ≈ id ∣_∣≈∣_∣ : (A : Type a)(B : Type b) → Type (a ⊔ b) ∣ A ∣≈∣ B ∣ = PointwiseBijection A B uncurry₀ : {A : Type a} → A → A → (A × A) uncurry₀ x y = x , y module _ {A : Type a} {B : Type b} where Curry : ((A × A) → B) → A → A → B Curry f x y = f (uncurry₀ x y) Uncurry : (A → A → B) → A × A → B Uncurry f (x , y) = f x y
The product and curried forms enjoy a definitional bijection — the round-trip composites reduce to id on the nose.
A×A→B≅A→A→B : ∣ (A × A → B) ∣=∣ (A → A → B) ∣ A×A→B≅A→A→B = record { to = Curry ; from = Uncurry ; to-from = refl ; from-to = refl }
Fin-indexed encodings¶
We now introduce the Fin-indexed encoding Fin 2 → A and transformations between it, the product form A × A, and the curried form A → A. The asymmetric behavior of these transformations under definitional equality is the central pedagogical content of the module.
module _ {A : Type a} where open Fin renaming (zero to z ; suc to s) A×A→Fin2A : A × A → Fin 2 → A A×A→Fin2A (x , y) z = x A×A→Fin2A (x , y) (s z) = y Fin2A→A×A : (Fin 2 → A) → A × A Fin2A→A×A u = u z , u (s z) Fin2A~A×A : {A : Type a} → Fin2A→A×A ∘ A×A→Fin2A ≡ id Fin2A~A×A = refl A×A~Fin2A-ptws : ∀ u → (A×A→Fin2A (Fin2A→A×A u)) ≈ u A×A~Fin2A-ptws u z = refl A×A~Fin2A-ptws u (s z) = refl A→A→Fin2A : A → A → Fin 2 → A A→A→Fin2A x y z = x A→A→Fin2A x y (s _) = y A→A→Fin2A' : A → A → Fin 2 → A A→A→Fin2A' x y = u where u : Fin 2 → A u z = x u (s z) = y A→A→Fin2A-ptws-agree : (x y : A) → ∀ i → (A→A→Fin2A x y) i ≡ (A→A→Fin2A' x y) i A→A→Fin2A-ptws-agree x y z = refl A→A→Fin2A-ptws-agree x y (s z) = refl A→A~Fin2A-ptws : (v : Fin 2 → A) → ∀ i → A→A→Fin2A (v z) (v (s z)) i ≡ v i A→A~Fin2A-ptws v z = refl A→A~Fin2A-ptws v (s z) = refl Fin2A : (Fin 2 → A) → Fin 2 → A Fin2A u z = u z Fin2A u (s z) = u (s z) Fin2A u (s (s ())) Fin2A≡ : (u : Fin 2 → A) → ∀ i → (Fin2A u) i ≡ u i Fin2A≡ u z = refl Fin2A≡ u (s z) = refl
Failed bijections¶
We can establish that CurryFin2 ∘ UncurryFin2 ≡ id reduces to refl, but the reverse composition UncurryFin2 ∘ CurryFin2 does not: it would require reducing λ {z → u z; (s z) → u (s z)} to u, which is η-expansion of a function out of Fin 2, and Agda's definitional equality does not include this reduction. Hence no definitional bijection between (Fin 2 → A) → B and A → A → B; only a pointwise one.
module _ {A : Type a} {B : Type b} where open Fin renaming (zero to z ; suc to s) lemma : (u : Fin 2 → A) → u ≈ (λ {z → u z ; (s z) → u (s z)}) lemma u z = refl lemma u (s z) = refl CurryFin2 : ((Fin 2 → A) → B) → A → A → B CurryFin2 f x y = f (A→A→Fin2A x y) UncurryFin2 : (A → A → B) → ((Fin 2 → A) → B) UncurryFin2 f u = f (u z) (u (s z)) CurryFin2~UncurryFin2 : CurryFin2 ∘ UncurryFin2 ≡ id CurryFin2~UncurryFin2 = refl CurryFin3 : {A : Type a} → ((Fin 3 → A) → B) → A → A → A → B CurryFin3 {A = A} f x₁ x₂ x₃ = f u where u : Fin 3 → A u z = x₁ u (s z) = x₂ u (s (s z)) = x₃ UncurryFin3 : (A → A → A → B) → ((Fin 3 → A) → B) UncurryFin3 f u = f (u z) (u (s z)) (u (s (s z))) Fin2A→B-to-A×A→B : ((Fin 2 → A) → B) → A × A → B Fin2A→B-to-A×A→B f = f ∘ A×A→Fin2A A×A→B-to-Fin2A→B : (A × A → B) → ((Fin 2 → A) → B) A×A→B-to-Fin2A→B f = f ∘ Fin2A→A×A Fin2A→B~A×A→B : Fin2A→B-to-A×A→B ∘ A×A→B-to-Fin2A→B ≡ id Fin2A→B~A×A→B = refl
The symmetric statement A×A→B-to-Fin2A→B ∘ Fin2A→B-to-A×A→B ≡ id fails for the same η-expansion reason: it would require λ u → (λ {z → u z; (s z) → u (s z)}) ≡ u, which Agda does not reduce.