Find file
Fetching contributors…
Cannot retrieve contributors at this time
469 lines (442 sloc) 109 KB
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="">
<title>Paolo Capriotti's blog</title>
<link href="" rel="self" />
<link href="" />
<name>Paolo Capriotti</name>
<title>Monads as lax functors</title>
<link href="" />
<summary type="html"><![CDATA[<p>Last week at <a href="">FP Lunch</a> I talked about how to generalise the notion of <em>monad</em> using lax functors to <span class="math inline">\({\mathsf{Cat}}\)</span>.</p>
<p>Let’s begin by reviewing the classical definition. A <strong>monad</strong> is given by the following data:</p>
<li>a category <span class="math inline">\({\mathcal{C}}\)</span>;</li>
<li>an endofunctor <span class="math inline">\(T : {\mathcal{C}}\to {\mathcal{C}}\)</span>;</li>
<li>natural transformations <span class="math inline">\(\eta : I \to T\)</span> and <span class="math inline">\(\mu : T \circ T \to T\)</span>;</li>
<p>satisfying certains laws (namely: <span class="math inline">\(\mu \circ \eta T = \mu \circ T \eta = {\mathsf{id}}\)</span> and <span class="math inline">\(\mu \circ T \mu = \mu \circ \mu T\)</span>). Note that the category <span class="math inline">\({\mathcal{C}}\)</span> is considered to be part of the data, rather than fixed beforehand.</p>
<p>In this post, I will illustrate a compact formulation of the above definition that can easily be generalised to include other similar notions, which appear from time to time in functional programming.</p>
<p>Here is the punchline:</p>
<p>A monad is a lax 2-functor from the terminal 2-category 1 to <span class="math inline">\({\mathsf{Cat}}\)</span>.</p>
<p>To make sense of this definition, we need to venture into the marvellous world of <em>higher categories</em>. If we take the definition of category that we are familiar with, we can regard it as some sort of 1-dimensional structure: we have a set of objects, which we can picture as points, and a set of arrows between them, which we imagine as (oriented) 1-dimensional lines.</p>
<p>It is then relatively easy to go one dimension up, and imagine an entity with 3 levels of structure: objects, morphisms, and 2-dimensional “cells” connecting arrows. This is what we call a 2-category.</p>
<p>More precisely, a 2-category is given by:</p>
<li>a set of <em>objects</em> (or 0-cells)</li>
<li>for any two objects <span class="math inline">\(x, y\)</span>, a set of <em>morphisms</em> (or 1-cells) <span class="math inline">\({\mathsf{hom}}(x, y)\)</span>;</li>
<li>for any two objects <span class="math inline">\(x, y\)</span>, and any two morphisms <span class="math inline">\(f, g : {\mathsf{hom}}(x, y)\)</span>, a set of <em>2-morphisms</em> <span class="math inline">\({\mathsf{hom}}_2 (f, g)\)</span>.</li>
<p>Of course, this cannot really be the complete definition of 2-category, as we also need to be able to compose morphisms and 2-morphisms, but we won’t go into much detail here. The interested reader can find more details on this <a href="">nLab page</a>.</p>
<p>The primary example of 2-category is <span class="math inline">\({\mathsf{Cat}}\)</span>, the 2-category of categories. Objects of <span class="math inline">\({\mathsf{Cat}}\)</span> are (ordinary) categories (also called 1-categories), morphisms are functors, and 2-morphisms are natural transformations. Another example is the terminal 2-category, containing only 1 object, and no non-identity morphisms or 2-morphisms.</p>
<p>As always happens in mathematics, every new structure that we define is accompanied by a corresponding notion of morphism. Given 2-categories <span class="math inline">\({\mathcal{C}}\)</span> and <span class="math inline">\({\mathcal{D}}\)</span>, we want to define what it means to give a “map” <span class="math inline">\({\mathcal{C}}\to {\mathcal{D}}\)</span> that respects the 2-category structure. We call such maps <em>2-functors</em>.</p>
<p>As it turns out, there are multiple ways to give a definition of 2-functor. They differ in the amount of <em>strictness</em> that they require. More precisely, a 2-functor <span class="math inline">\({\mathcal{C}}\to {\mathcal{D}}\)</span> is given by:</p>
<li>a function <span class="math inline">\(F\)</span> mapping objects of <span class="math inline">\({\mathcal{C}}\)</span> to objects of <span class="math inline">\({\mathcal{D}}\)</span>;</li>
<li>for any two objects <span class="math inline">\(x, y\)</span> of <span class="math inline">\({\mathcal{C}}\)</span>, a function (also denoted <span class="math inline">\(F\)</span>) mapping morphisms between <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span> in <span class="math inline">\({\mathcal{C}}\)</span> to morphisms between <span class="math inline">\(F x\)</span> and <span class="math inline">\(F y\)</span> in <span class="math inline">\({\mathcal{D}}\)</span>;</li>
<li>for any two objects <span class="math inline">\(x, y\)</span> of <span class="math inline">\({\mathcal{C}}\)</span>, and morphisms <span class="math inline">\(f, g : {\mathsf{hom}}(x, y)\)</span>, a function mapping 2-morphisms between <span class="math inline">\(f\)</span> and <span class="math inline">\(g\)</span> to 2-morphisms between <span class="math inline">\(F f\)</span> and <span class="math inline">\(F g\)</span>;</li>
<p>subject to certain “functoriality” properties. We can make this functoriality requirement precise in a number of different (non-equivalent) ways.</p>
<p>First, we might directly generalise the functoriality properties for functors, and require: <span class="math display">\[
&amp; F{\mathsf{id}}= {\mathsf{id}}, \\
&amp; F (g \circ f) = F g \circ F f.
<p>If we do that, we get the notion of <em>strict functor</em>. However, the elements appearing in the above equations are objects of certain categories (namely, <span class="math inline">\({\mathsf{hom}}\)</span>-categories of <span class="math inline">\({\mathcal{D}}\)</span>), and if category theory has taught us anything, it is the idea that comparing objects of categories up to equality is often not very fruitful.</p>
<p>Therefore, we are naturally lead to the notion of <em>pseudofunctor</em>, which weakens the equalities to <em>isomorphisms</em>: <span class="math display">\[
&amp; F{\mathsf{id}}\cong {\mathsf{id}}, \\
&amp; F (g \circ f) \cong F g \circ F f.
<p>However, we are interested in an even weaker notion here, called <em>lax 2-functor</em>, which replaces the isomorphisms above with arbitrary (possibly not invertible) 2-morphisms: <span class="math display">\[
&amp; {\mathsf{id}}\to F {\mathsf{id}}, \\
&amp; F g \circ F f \to F (g \circ f).
<p>The direction of the arrows can be reversed, yielding the dual notion of <em>oplax functor</em>, which we won’t need here.</p>
<p>Now we understand all the terminology used in the definition above. Let <span class="math inline">\(F : 1 \to {\mathsf{Cat}}\)</span> be a lax 2-functor. At the level of objects, <span class="math inline">\(F\)</span> maps the unique object of <span class="math inline">\(1\)</span> to <span class="math inline">\({\mathsf{Cat}}\)</span>, which amounts to just picking a single category <span class="math inline">\({\mathcal{C}}\)</span>. At the level of morphisms, we map the single (identity) morphisms of 1 to a functor <span class="math inline">\(T: {\mathcal{C}}\to {\mathcal{C}}\)</span>. Now, the “lax structure” produces 2-morphisms in <span class="math inline">\({\mathsf{Cat}}\)</span> (i.e. natural transformations): <span class="math inline">\(\eta : I \to T\)</span> and <span class="math inline">\(\mu : T \circ T \to T\)</span>.</p>
<p>So it looks like lax 2-functors to <span class="math inline">\({\mathsf{Cat}}\)</span>, at least ignoring certain details that we haven’t discussed, correspond perfectly to the classical definition of monad. I encourage the interested reader to look at the complete definition of lax functor, and verify that everything does indeed match, including the monad laws.</p>
<p>After all this work, generalising the definition is now extremely easy: just replace the 2-category 1 with a more general category. A simple example is: given a monoid <span class="math inline">\(S\)</span>, regard <span class="math inline">\(S\)</span> as a 2-category with 1 object and no non-trivial 2-morphism. Lax functors <span class="math inline">\(S \to {\mathsf{Cat}}\)</span> are exactly Wadler’s <a href="">indexed monads</a>.</p>
<p>It is also possible (although slightly more involved) to recover Atkey’s <a href="">parameterised monads</a> as lax functors. I’ll leave this as a fun exercise.</p>]]></summary>
<title>Free monads in category theory (part 3)</title>
<link href="" />
<summary type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>In the previous post, we investigated free monads, i.e. those whose monad algebras are the same as algebras of some functor. In general, however, not all monads are free, not even in Haskell! Nevertheless, monad algebras can often be regarded as algebras of some functor, satisfying certain “algebraic laws”.</p>
<p>In the first post of the series, we looked at the list monad <span class="math inline">\(L\)</span>. We observed that monad algebras of <span class="math inline">\(L\)</span> can be regarded as monoids, which is to say they are algebras of the functor <span class="math inline">\(F\)</span> given by <span class="math inline">\(F X = 1 + X²\)</span>, subject to unit and associativity laws.</p>
<p>The list example is interesting, because it suggests a strong connection between monads and algebraic structures. Can we always regard algebraic structures (such as groups, rings, vector spaces, etc…) as the algebras of some monad?</p>
<p>In this post, we will try to generalise this example to other monads by developing a categorical definition of <em>algebraic theory</em> based on monads and monad algebras.</p>
<h2 id="algebraic-theories">Algebraic theories</h2>
<p>The theory of monoids is a particular instance of a general pattern that occurs over and over in mathematics. We have a set of operations, each with a specified arity, and a set of laws that these operations are required to satisfy. The laws all have the form of equations with universally quantified variables.</p>
<p>For monoids, we have two operations: a unit <span class="math inline">\(e\)</span>, which is a nullary operation (i.e. a constant), and multiplication <span class="math inline">\(·\)</span>, a binary operation (written infix). The laws should be very familiar: <span class="math display">\[
e · x &amp; = x \\
x · e &amp; = x \\
x · (y · z) &amp; = (x · y) · z
\]</span> where every free variable is implicitly considered to be universally quantified.</p>
<p>As we observed in the first post of this series, the functor <span class="math inline">\(F\)</span> corresponding to the algebraic theory of monoids is given by <span class="math inline">\(F X = 1 + X²\)</span>. Algebras of <span class="math inline">\(F\)</span> are sets equipped with the operations of a monoid, but there is no requirement that they satisfy the laws.</p>
<p>Since <span class="math inline">\(F\)</span> is polynomial, it has an algebraically free monad <span class="math inline">\(F^*\)</span>, so <span class="math inline">\(F^* X\)</span> is in particular an <span class="math inline">\(F\)</span>-algebra. If we focus on the first law above, we see that it just consists of a pair of terms in <span class="math inline">\(F^* X\)</span>, parameterised over some unspecified element <span class="math inline">\(x : X\)</span>. This can be expressed as a natural transformation: <span class="math display">\[
X → F^*X × F^* X
\]</span> The same holds for the second law, while the third can be regarded as a function: <span class="math display">\[
X³ → F^*X × F^*X
<p>We can assemble those three functions into a single datum, consisting of a pair of natural transformations: <span class="math display">\[
X + X + X³ ⇉ F^* X
<p>If we set <span class="math inline">\(G X = X + X + X³\)</span>, we have that the laws can be summed up concisely by giving a pair of natural transformations: <span class="math display">\[
G ⇉ F^*,
\]</span> which, since algebraically free monads are free, is the same as a parallel pair of monad morphisms: <span class="math display">\[
l, r : G^* ⇉ F^*,
\]</span> and this is something that we can easily generalise. Namely, we say that an <em>algebraic theory</em> is a parallel pair of morphisms of algebraically free monads.</p>
<p>Note that the terminology here is a bit fuzzy. Some authors might refer to the parallel pair above as a <em>presentation</em> of an algebraic theory. It ultimately depends on whether or not you want to consider theories with different syntactical presentations but identical models to be equal. With our definition, they would be considered different.</p>
<h2 id="models">Models</h2>
<p>To really motivate this definition, we now need to explain what the models of an algebraic theory are. This is quite easy if we just follow our derivation of the general definition from the example.</p>
<p>We know that a monoid is an <span class="math inline">\(F\)</span>-algebra <span class="math inline">\(θ : F X → X\)</span> that satisfies the monoid laws. Since <span class="math inline">\(F\)</span>-algebras are the same as <span class="math inline">\(F^*\)</span>-algebras, we can work with the corresponding <span class="math inline">\(F^*\)</span>-algebra instead, which we denote by <span class="math inline">\(θ^* : F^*X → X\)</span>.</p>
<p>This algebra satisfies the laws exactly when the two natural transformations above become equal when composed with <span class="math inline">\(θ^*\)</span>, i.e. when <span class="math inline">\(θ^* ∘ l = θ^* ∘ r\)</span>.</p>
<p>We thus define the category of models of an algebraic theory <span class="math inline">\(l, r : G^* ⇉ F^*\)</span> as the full subcategory of <span class="math inline">\(\cat{Alg}_F ≅ \cat{mAlg}_{F^*}\)</span> consisting of all those monad algebras <span class="math inline">\(θ^* : F^* X → X\)</span> such that <span class="math inline">\(θ^* ∘ l = θ^* ∘ r\)</span>.</p>
<p>Now, we know that, in the case of monoids, this subcategory is monadic over <span class="math inline">\(\set\)</span>, but is this true in general?</p>
<p>We begin by defining the notion of a <em>free model</em> for some algebraic theory. In the monoid example, we used the list monad to build a monoid out of any set, and then proceeded to prove that this construction gives the left adjoint of the forgetful functor <span class="math inline">\(\cat{Alg}_F → \set\)</span>. This is of course the first step towards proving monadicity.</p>
<p>In general, there does not seem to be a way to generalise this construction directly. We pulled the list monad out of a hat, and showed that it was exactly the monad that we were looking for. We did not derive it using the functor <span class="math inline">\(F\)</span> in a systematic way that we could replicate in the general case.</p>
<p>Fortunately, there is another way to produce the free monoid over a set <span class="math inline">\(X\)</span>. We start with the free <span class="math inline">\(F\)</span>-algebra <span class="math inline">\(F^* X\)</span>, then <em>quotient</em> it according to the laws. Intuitively, we define an equivalence relation that relates two elements <span class="math inline">\(t₁\)</span> and <span class="math inline">\(t₂\)</span> whenever there is a law that requires them to be equal.</p>
<p>The straightforward way to formalise this intuition is to take the equivalence relation generated by such pairs <span class="math inline">\((t₁, t₂)\)</span>, then take the corresponding quotient. A more conceptual approach is to say that <span class="math inline">\(T X\)</span> is obtained as a coequaliser: <span class="math display">\[
G^* X ⇉ F^* X → T X.
<p>In the monoid example, <span class="math inline">\(F^* X\)</span> is the set of all trees with leaves labelled by elements of <span class="math inline">\(X\)</span>. If we regard a tree as a parenthesised string of elements of <span class="math inline">\(X\)</span>, then the equivalence relation on <span class="math inline">\(F^*\)</span> given by the coequaliser above corresponds to identifying strings with the same underlying <em>list</em> of elements but possibly different parenthesizations. Therefore, <span class="math inline">\(T X\)</span> is clearly isomorphic to the list monad.</p>
<h2 id="conclusion">Conclusion</h2>
<p>More generally, we can take any algebraic theory, which we defined as a parallel pair of monad morphisms between free monads <span class="math inline">\(F^*\)</span> and <span class="math inline">\(G^*\)</span>, and take the coequaliser in the category of (finitary) monads.</p>
<p>With some reasonable assumptions on the functors <span class="math inline">\(F\)</span> and <span class="math inline">\(G\)</span>, we can show that this coequaliser always exists, and that the algebras of the resulting monad are exactly the models of the algebraic theory we started with.</p>
<h2 id="further-reading">Further reading</h2>
<p>This concludes my series on the underlying theory of free monads and their relation with universal algebra.</p>
<p>Here is a list of resources where you can learn more about this topic:</p>
<h4 id="michael-barr-and-charles-wells-toposes-triples-and-theories">Michael Barr and Charles Wells, Toposes, Triples and Theories</h4>
<p>“Triple” is the old term for monads. Chapter 3 is about the monadicity theorem and some of the material that I covered in this series.</p>
<h4 id="saunders-mac-lane-categories-for-the-working-mathematician">Saunders Mac Lane, Categories for the Working Mathematician</h4>
<p>Chapter 6 is about monads and their algebras.</p>
<h4 id="steve-awodey-category-theory">Steve Awodey, Category Theory</h4>
<p>The last chapter explains the relationship between initial algebras and monadic functors.</p>
<h4 id="francis-borceux-handbook-of-categorical-algebra">Francis Borceux, Handbook of Categorical Algebra</h4>
<p>A very comprehensive resource, with detailed proofs.</p>]]></summary>
<title>Free monads in category theory (part 2)</title>
<link href="" />
<summary type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>In the <a href="">previous post</a>, I introduced the notion of <em>monadic functor</em>, exemplified by the forgetful functor from the category of monoids to <span class="math inline">\(\set\)</span>. We saw that monoids form a subcategory of the category of algebras of the functor <span class="math inline">\(F\)</span> defined by <span class="math inline">\(F X = 1 + X²\)</span>, and we observed that those are the same as the monad algebras of the list monad.</p>
<h2 id="algebraically-free-monads">Algebraically free monads</h2>
<p>More generally, we can try different subcategories of <span class="math inline">\(\cat{Alg}_F\)</span> and check whether they are monadic as well. So let’s start with possibly the simplest one: the whole of <span class="math inline">\(\cat{Alg}_F\)</span>.</p>
<p>This leads us to the following definition: we say that an endofunctor <span class="math inline">\(F\)</span> <em>admits an algebraically free monad</em> if <span class="math inline">\(\cat{Alg}_F\)</span> is monadic. The corresponding monad is called the <em>algebraically free monad</em> over <span class="math inline">\(F\)</span>.</p>
<p>Informally, the algebraically free monad over <span class="math inline">\(F\)</span> is a monad <span class="math inline">\(T\)</span> such that monad algebras of <span class="math inline">\(T\)</span> are the same as functor algebras of <span class="math inline">\(F\)</span>.</p>
<p>Unfortunately, not all functors admit an algebraically free monad. For example, it is easy to see that the powerset functor does not.</p>
<h2 id="free-monads-as-initial-algebras">Free monads as initial algebras</h2>
<p>The <a href="">free</a> package on Hackage defines something called “free monad” for every Haskell functor. What does this have to do with the notion of algebraically free monad defined above?</p>
<p>Here is the definition of <code>Free</code> from the above package:</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">Free</span> f a
<span class="fu">=</span> <span class="dt">Pure</span> a
<span class="fu">|</span> <span class="dt">Free</span> (f (<span class="dt">Free</span> f a))</code></pre></div>
<p>Translating into categorical language, we can define, for an endofunctor <span class="math inline">\(F\)</span>, the functor <span class="math inline">\(F^*\)</span>, which returns, for a set <span class="math inline">\(X\)</span>, a fixpoint of the functor <span class="math display">\[
G Y = X + F Y.
<p>Let’s assume that the fixpoint is to be intended as inductive, i.e. as an initial algebra. Therefore, we get, for all objects <span class="math inline">\(X\)</span>, an initial algebra: <span class="math display">\[
X + F (F^* X) → F^* X.
<p>Of course, those initial algebras might not exist, but they do if we choose <span class="math inline">\(F\)</span> carefully. For example, if <span class="math inline">\(F\)</span> is polynomial, then all the functors <span class="math inline">\(G\)</span> above are also polynomial, thus they have initial algebras.</p>
<p>In general, if we assume that those initial algebras all exist, then we can prove that the resulting functor <span class="math inline">\(F^*\)</span> is a monad, and is indeed the algebraically free monad over <span class="math inline">\(F\)</span>.</p>
<p>We will first show that <span class="math inline">\(F^*\)</span> allows us to define a left adjoint <span class="math inline">\(L\)</span> for the forgetful functor <span class="math inline">\(U : \cat{Alg}_F → \set\)</span>. In fact, for any set <span class="math inline">\(X\)</span>, let the carrier of <span class="math inline">\(L X\)</span> be <span class="math inline">\(F^* X\)</span>, and define the algebra morphism by restriction from the initial algebra structure on <span class="math inline">\(F^* X\)</span>: <span class="math display">\[
F (F^* X) → X + F (F^* X) → F^* X.
<p>By definition, <span class="math inline">\(F^* X\)</span> is the initial object in the category of algebras of the functor <span class="math inline">\(Y ↦ X + F Y\)</span>. Moreover, it is easy to see that the latter category is equivalent to the comma category <span class="math inline">\((X ↓ U)\)</span>, where the equivalence maps <span class="math inline">\(F^* X\)</span> to the obvious morphism <span class="math inline">\(X → U L X\)</span>. By the <a href="">characterisation of adjunctions in terms of universal arrows</a>, it follows that <span class="math inline">\(L\)</span> is left adjoint to <span class="math inline">\(U\)</span>. Clearly, <span class="math inline">\(U L = F^*\)</span>, therefore <span class="math inline">\(F^*\)</span> is a monad.</p>
<p>To conclude the proof, we need to show that the adjunction <span class="math inline">\(L ⊣ U\)</span> is monadic, i.e. that the comparison functor from <span class="math inline">\(F\)</span>-algebras to <span class="math inline">\(F^*\)</span>-algebras is an equivalence. One way to do that is to appeal to <a href="">Beck’s monadicity theorem</a>. Verifying the hypotheses is a simple exercise.</p>
<p>It is also instructive to look at the comparison functor as implemented in haskell:</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">iter ::</span> <span class="dt">Functor</span> f <span class="ot">=&gt;</span> (f x <span class="ot">→</span> x) <span class="ot">→</span> (<span class="dt">Free</span> f x <span class="ot">→</span> x)
iter θ (<span class="dt">Pure</span> x) <span class="fu">=</span> x
iter θ (<span class="dt">Free</span> t) <span class="fu">=</span> θ (fmap (iter θ) t)</code></pre></div>
<p>and its inverse</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell">uniter <span class="fu">:</span> <span class="dt">Functor</span> f <span class="ot">=&gt;</span> (<span class="dt">Free</span> f x <span class="ot">→</span> x) <span class="ot">→</span> (f x <span class="ot">→</span> x)
uniter ψ <span class="fu">=</span> ψ <span class="fu">.</span> liftF
<span class="kw">where</span> liftF <span class="fu">=</span> <span class="dt">Free</span> <span class="fu">.</span> fmap <span class="dt">Pure</span></code></pre></div>
<p>It is not hard to prove directly, using equational reasoning, that <code>iter θ</code> is a monad algebra, and that <code>iter</code> and <code>uniter</code> are inverses to each other.</p>
<h2 id="algebraically-free-monads-are-free">Algebraically free monads are free</h2>
<p>The documentation for <code>Free</code> says:</p>
<p>A Monad <code>n</code> is a free Monad for <code>f</code> if every monad homomorphism from <code>n</code> to another monad <code>m</code> is equivalent to a natural transformation from <code>f</code> to <code>m</code></p>
<p>which doesn’t look at all like our definition of algebraically free monad. Rather, this says that <span class="math inline">\(N\)</span> is defined to be the <em>free monad</em> over <span class="math inline">\(F\)</span> if the canonical natural transformation <span class="math inline">\(F → N\)</span> is a universal arrow from <span class="math inline">\(F\)</span> to the forgetful functor <span class="math inline">\(\cat{Mon}(\set) → \cat{Func}(\set, \set)\)</span>.</p>
<p>If that forgetful functor had a left adjoint, then we could just say that the free monad is obtained by applying this left adjoint to any endofunctor. This is actually the case if we replace <span class="math inline">\(\set\)</span> with a so-called <em>algebraically complete category</em>, such as the ones modelled by Haskell, where the left adjoint is given by the (higher order) functor <code>Free</code>.</p>
<p>In <span class="math inline">\(\set\)</span>, however, we need to stick to the more awkward definition in terms of universal arrows, as not all functors are going to admit free monads. In any case, the relationship with the previously defined notion of algebraically free monad is not immediately clear.</p>
<p>Fortunately, we can prove that a monad is algebraically free if and only if it is free! Proving that an algebraically free monad <span class="math inline">\(F^*\)</span> on <span class="math inline">\(F\)</span> is free amounts to proving that the following natural transformation (corresponding to <code>liftF</code> in the Haskell code above): <span class="math display">\[
F X @&gt;{F η}&gt;&gt; F (F^* X) @&gt;&gt;&gt; F^* X
\]</span> is universal, which is a simple exercise.</p>
<p>To prove the converse, we will be using Haskell notation. Suppose given a functor <code>f</code>, and a monad <code>t</code> that is free on <code>f</code>. Therefore, we have a natural transformation:</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">l ::</span> f x <span class="ot">→</span> t x</code></pre></div>
<p>and a function that implements the universal property for <code>t</code>:</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">hoist ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> (<span class="ot">∀</span> x <span class="fu">.</span> f x <span class="ot">→</span> m x) <span class="ot">→</span> t x <span class="ot">→</span> m x</code></pre></div>
<p>Now we define a functor <span class="math inline">\(\set → \cat{Alg}_f\)</span> which is going to be the left adjoint of the forgetful functor. The carrier of this functor is given by <code>t</code> itself, so we only need to define the algebra morphism:</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">alg ::</span> f (t x) <span class="ot">→</span> t x
alg u <span class="fu">=</span> join (l u)</code></pre></div>
<p>To show that this functor is the sought left adjoint, we have to fix a type <code>x</code> and an <code>f</code>-algebra <code>θ : f y → y</code>, define functions:</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell">φ<span class="ot"> ::</span> (x <span class="ot">→</span> y) <span class="ot">→</span> (t x <span class="ot">→</span> y)
ψ<span class="ot"> ::</span> (t x <span class="ot">→</span> y) <span class="ot">→</span> (x <span class="ot">→</span> y)</code></pre></div>
<p>then prove that <code>φ g</code> is an <code>f</code>-algebra morphism for all <code>g : x → y</code>, and that <code>φ</code> and <code>ψ</code> are inverses to each other.</p>
<p>The function <code>ψ</code> is easy to implement:</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell">ψ a h <span class="fu">=</span> h <span class="fu">.</span> return</code></pre></div>
<p>Defining <code>φ</code> is a bit more involved. The only tool at our disposal to define functions out of <code>t x</code> is <code>hoist</code>. For that, we need a monad <code>m</code>, and a natural transformation <code>f → m</code>.</p>
<p>The trick is to consider the <em>continuation monad</em> <code>Cont y</code>. Using <code>θ</code>, we define a natural transformation</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">w ::</span> f z <span class="ot">→</span> <span class="dt">Cont</span> y z
w u <span class="fu">=</span> <span class="dt">Cont</span> (\k <span class="ot">-&gt;</span> θ (fmap k u))</code></pre></div>
<p>on which we can apply the universal property of <code>t</code> to get <code>φ</code>:</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell">φ g <span class="fu">=</span> (<span class="ot">`runCont`</span> id) <span class="fu">.</span> hoist w <span class="fu">.</span> fmap g</code></pre></div>
<p>From here, the proof proceeds by straightforward equational reasoning, and is left as an exercise.</p>
<h2 id="conclusion">Conclusion</h2>
<p>We looked at two definitions of “free monad”, proved that they are equivalent, and shown the relationship with the Haskell definition of <code>Free</code>. In the next post, we will resume our discussion of algebraic theories “with laws” and try to approach them from the point of view of free monads and monadic functors.</p>]]></summary>
<title>Free monads in category theory (part 1)</title>
<link href="" />
<summary type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Free monads can be used in Haskell for modelling a number of different concepts: trees with arbitrary branching, terms with free variables, or program fragments of an EDSL.</p>
<p>This series of posts is <em>not</em> an introduction to free monads in Haskell, but to the underlying theory. In the following, we will work in the category <span class="math inline">\(\set\)</span> of sets and functions. However, most of what we say can be trivially generalised to an arbitrary category.</p>
<h2 id="algebras-of-a-functor">Algebras of a functor</h2>
<p>If <span class="math inline">\(F\)</span> is an endofunctor on <span class="math inline">\(\set\)</span>, an <strong>algebra</strong> of <span class="math inline">\(F\)</span> is a set <span class="math inline">\(X\)</span> (called its <em>carrier</em>), together with a morphism <span class="math inline">\(FX → X\)</span>. Algebras of <span class="math inline">\(F\)</span> form a category, where morphisms are functions of their respective carriers that make the obvious square commute.</p>
<p>Bartosz Milewski wrote a nice introductory <a href="">post on functor algebras</a> from the point of view of functional programming, which I strongly recommend reading to get a feel for why it is useful to consider such objects.</p>
<p>More abstractly, a functor <span class="math inline">\(F : \set → \set\)</span> generalises the notion of a <em>signature</em> of an algebraic theory. For a signature with <span class="math inline">\(a_i\)</span> operators of arity <span class="math inline">\(i\)</span>, for <span class="math inline">\(i = 0, \ldots, n\)</span>, the corresponding functor is the polynomial: <span class="math display">\[
F X = a₀ + a₁ × X + ⋯ + a_n × X^n,
\]</span> where the natural number <span class="math inline">\(a_i\)</span> denotes a finite set of cardinality <span class="math inline">\(a_i\)</span>.</p>
<p>For example, the theory of monoids has 1 nullary operation, and 1 binary operation. That results in the functor: <span class="math display">\[
F X = 1 + X^2
<p>Suppose that <span class="math inline">\((X, θ)\)</span> is an algebra for this particular functor. That is, <span class="math inline">\(X\)</span> is a set, and <span class="math inline">\(θ\)</span> is a function <span class="math inline">\(1 + X² → X\)</span>. We can split <span class="math inline">\(θ\)</span> into its two components: <span class="math display">\[
θ_e : 1 → X,
\]</span> which we can simply think of as an element of <span class="math inline">\(X\)</span>, and <span class="math display">\[
θ_m : X × X → X.
<p>So we see that an algebra for <span class="math inline">\(F\)</span> is exactly a set, together with the operations of a monoid. However, there is nothing that tells us that <span class="math inline">\(X\)</span> is indeed a monoid with those operations!</p>
<p>In fact, for <span class="math inline">\(X\)</span> to be a monoid, the operations above need to satisfy the following laws: <span class="math display">\[
&amp; θ_m (θ_e(∗), x) = x \\
&amp; θ_m (x, θ_e(∗)) = x \\
&amp; θ_m (θ_m (x, y), z) = θ_m (x, θ_m (y, z)).
<p>However, any two operations <span class="math inline">\(θ_e\)</span> and <span class="math inline">\(θ_m\)</span> with the above types can be assembled into an <span class="math inline">\(F\)</span>-algebra, regardless of whether they do satisfy the monoid laws or not.</p>
<h2 id="lawful-algebras">“Lawful” algebras</h2>
<p>The above example shows that functor algebras don’t quite capture the general notion of “algebraic structure” in the usual sense. They can express the idea of a set equipped with operations complying to a given signature, but we cannot enforce any sort of <em>laws</em> on those operations.</p>
<p>For the monoid example above, we noticed that we can realise any actual monoid as an <span class="math inline">\(F\)</span>-algebra (for <span class="math inline">\(FX = 1 + X²\)</span>), but that not every such algebra is a monoid. This means that monoids can be regarded as the objects of the subcategory of <span class="math inline">\(\cat{Alg}_F\)</span> consisting of the “lawful” algebras (exercise: make this statement precise and prove it).</p>
<p>Therefore, we have the following commutative diagram of functors: <span class="math display">\[
\mathsf{Mon} @&gt;⊆&gt;&gt; \mathsf{Alg}_F\\
\mathsf{Set} @&gt;=&gt;&gt; \mathsf{Set}
<p>and it is easy to see that <span class="math inline">\(U\)</span> (which is just the restriction of the obvious forgetful functor <span class="math inline">\(\cat{Alg}_F → \set\)</span> on the right side of the diagram) has a left adjoint <span class="math inline">\(L\)</span>, the functor that returns the free monoid on a set.</p>
<p>Explicitly, <span class="math inline">\(LX\)</span> has <span class="math inline">\(X^*\)</span> as carrier (i.e. the set of <em>lists</em> of elements of <span class="math inline">\(X\)</span>), and the algebra is given by the coproduct of the function <span class="math inline">\(1 → X^*\)</span> that selects the empty list, and the list concatenation function <span class="math inline">\(X^* × X^* → X^*\)</span>.</p>
<p>In Haskell, this algebra looks like:</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">alg ::</span> <span class="dt">Either</span> () ([x], [x]) <span class="ot">→</span> [x]
alg (<span class="dt">Left</span> _) <span class="fu">=</span> []
alg (<span class="dt">Right</span> (xs, ys)) <span class="fu">=</span> xs <span class="fu">++</span> ys</code></pre></div>
<p>The endofunctor <span class="math inline">\(UL\)</span>, obtained by taking the carrier of the free monoid, is a monad, namely the <em>list monad</em>.</p>
<h2 id="algebras-of-a-monad">Algebras of a monad</h2>
<p>Given a monad <span class="math inline">\((T, η, μ)\)</span> on <span class="math inline">\(\set\)</span>, a monad algebra of <span class="math inline">\(T\)</span> is an algebra <span class="math inline">\((X, θ)\)</span> of the underlying functor of <span class="math inline">\(T\)</span>, such that the following two diagrams commute:</p>
<p><span class="math display">\[
\begin{CD} X @&gt;η&gt;&gt; T X \\
@V=VV @VVθV\\
X @&gt;=&gt;&gt; X
<p><span class="math display">\[
T(T X) @&gt;μ&gt;&gt; T X \\
@V{T θ}VV @VVθV \\
T X @&gt;θ&gt;&gt; X
<p>In Haskell notation, this means that the following two equations are satisfied:</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell">θ (return x) <span class="fu">=</span> x
θ (fmap θ m) <span class="fu">=</span> θ (join m)</code></pre></div>
<p>In the case where the monad <span class="math inline">\(T\)</span> returns the set of “terms” of some language for a given set of free variables, a monad algebra can be thought of as an evaluation function.</p>
<p>The first law says that a variable is evaluated to itself, while the second law expresses the fact that when you have a “term of subterms”, you can either evaluate every subterm and then evaluate the resulting term, or regard it as a single term and evaluate it directly, and these two procedures should give the same result.</p>
<p>Naturally, monad algebras of <span class="math inline">\(T\)</span> form a full subcategory of <span class="math inline">\(\cat{Alg}_T\)</span> which we denote by <span class="math inline">\(\cat{mAlg}_T\)</span>.</p>
<p>We can now go back to our previous example, and look at what the monad algebras for the list monad are. Suppose we have a set <span class="math inline">\(X\)</span> and a function <span class="math inline">\(θ : X^* → X\)</span> satisfying the two laws stated above.</p>
<p>We can now define a monoid instance for <span class="math inline">\(X\)</span>. In Haskell, it looks like this:</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">Monoid</span> <span class="dt">X</span> <span class="kw">where</span>
empty <span class="fu">=</span> θ []
mappend x y <span class="fu">=</span> θ [x, y]</code></pre></div>
<p>The monoid laws follow easily from the monad algebra laws. Verifying them explicitly is a useful (and fun!) exercise. Vice versa, any monoid can be given a structure of a <span class="math inline">\(T\)</span>-algebra, simply by taking <code>mconcat</code> as <span class="math inline">\(θ\)</span>.</p>
<p>Therefore, we can extend the previous diagram of functors with an equivalence of categories: <span class="math display">\[
\mathsf{mAlg}_T @&gt;≅&gt;&gt; \mathsf{Mon} @&gt;⊆&gt;&gt; \mathsf{Alg}_F\\
\mathsf{Set} @&gt;=&gt;&gt; \mathsf{Set} @&gt;=&gt;&gt; \mathsf{Set}
\]</span> where the top-left equivalence (which is actually an isomorphism) is determined by the <code>Monoid</code> instance that we defined above, while its inverse is given by <code>mconcat</code>.</p>
<p>Let’s step back at this whole derivation, and reflect on what it is exactly that we have proved. We started with some category of “lawful” algebras, a subcategory of <span class="math inline">\(\cat{Alg}_F\)</span> for some endofunctor <span class="math inline">\(F\)</span>. We then observed that the forgetful functor from this category to <span class="math inline">\(\set\)</span> admits a left adjoint <span class="math inline">\(L\)</span>. We then considered monad algebras of the monad <span class="math inline">\(UL\)</span>, and we finally observed that these are exactly those “lawful” algebras that we started with!</p>
<h2 id="monadic-functors">Monadic functors</h2>
<p>We will now generalise the previous example to an arbitrary category of algebra-like objects.</p>
<p>Suppose <span class="math inline">\(\cat{D}\)</span> is a category equipped with a functor <span class="math inline">\(G : \cat{D} → \set\)</span>. We want to think of <span class="math inline">\(G\)</span> as some sort of “forgetful” functor, stripping away all the structure on the objects of <span class="math inline">\(\cat{D}\)</span>, and returning just their carrier.</p>
<p>To make this intuition precise, we say that <span class="math inline">\(G\)</span> is <em>monadic</em> if:</p>
<ol style="list-style-type: decimal">
<li><span class="math inline">\(G\)</span> has a left adjoint <span class="math inline">\(L\)</span></li>
<li>The <em>comparison functor</em> <span class="math inline">\(\cat{D} → \cat{mAlg}_T\)</span> is an equivalence of categories, where <span class="math inline">\(T = GL\)</span>.</li>
<p>The comparison functor is something that we can define for any adjunction <span class="math inline">\(L ⊢ G\)</span>, and it works as follows. For any object <span class="math inline">\(A : \cat{D}\)</span>, it returns the monad algebra structure on <span class="math inline">\(G A\)</span> given by <span class="math inline">\(G \epsilon\)</span>, where <span class="math inline">\(\epsilon\)</span> is the counit of the adjunction (exercise: check all the details).</p>
<p>So, what this definition is saying is that a functor is monadic if it really is the forgetful functor for the category of monad algebras for some monad. Sometimes, we say that a <em>category</em> is monadic, when the functor <span class="math inline">\(G\)</span> is clear.</p>
<p>The monoid example above can then be summarised by saying that the category of monoids is monadic.</p>
<h2 id="conclusion">Conclusion</h2>
<p>I’ll stop here for now. In the next post we will look at algebraically free monads and how they relate to the corresponding <a href="">Haskell definition</a>.</p>]]></summary>
<title>Another proof of function extensionality</title>
<link href="" />
<summary type="html"><![CDATA[<p>The fact that the univalence axiom implies function extensionality is one of the most well-known results of Homotopy Type Theory.</p>
<p>The <a href="">original proof</a> by Voevodsky has been simplified over time, and eventually assumed the distilled form presented in the <a href="">HoTT book</a>.</p>
<p>All the various versions of the proof have roughly the same outline. They first show that the <em>weak function extensionality principle</em> (WFEP) follows from univalence, and then prove that this is enough to establish function extensionality.</p>
<p>Following the book, WFEP is the statement that contractible types are closed under <span class="math">\(Π\)</span>, i.e.:</p>
<pre class="Agda"><code><a name="1192" href="#1192" class="Function">WFEP</a><a name="1196"> </a><a name="1197" class="Symbol">:</a><a name="1198"> </a><a name="1199" class="Symbol">∀</a><a name="1200"> </a><a name="1201" href="#1201" class="Bound">i</a><a name="1202"> </a><a name="1203" href="#1203" class="Bound">j</a><a name="1204"> </a><a name="1205" class="Symbol">→</a><a name="1206"> </a><a name="1207" class="PrimitiveType">Set</a><a name="1210"> </a><a name="1211" class="Symbol">_</a><a name="1212">
</a><a name="1213" href="#1192" class="Function">WFEP</a><a name="1217"> </a><a name="1218" href="#1218" class="Bound">i</a><a name="1219"> </a><a name="1220" href="#1220" class="Bound">j</a><a name="1221"> </a><a name="1222" class="Symbol">=</a><a name="1223"> </a><a name="1224" class="Symbol">{</a><a name="1225" href="#1225" class="Bound">A</a><a name="1226"> </a><a name="1227" class="Symbol">:</a><a name="1228"> </a><a name="1229" class="PrimitiveType">Set</a><a name="1232"> </a><a name="1233" href="#1218" class="Bound">i</a><a name="1234" class="Symbol">}{</a><a name="1236" href="#1236" class="Bound">B</a><a name="1237"> </a><a name="1238" class="Symbol">:</a><a name="1239"> </a><a name="1240" href="#1225" class="Bound">A</a><a name="1241"> </a><a name="1242" class="Symbol">→</a><a name="1243"> </a><a name="1244" class="PrimitiveType">Set</a><a name="1247"> </a><a name="1248" href="#1220" class="Bound">j</a><a name="1249" class="Symbol">}</a><a name="1250">
</a><a name="1260" class="Symbol">→</a><a name="1261"> </a><a name="1262" class="Symbol">((</a><a name="1264" href="#1264" class="Bound">x</a><a name="1265"> </a><a name="1266" class="Symbol">:</a><a name="1267"> </a><a name="1268" href="#1225" class="Bound">A</a><a name="1269" class="Symbol">)</a><a name="1270"> </a><a name="1271" class="Symbol">→</a><a name="1272"> </a><a name="1273" href="" class="Function">contr</a><a name="1278"> </a><a name="1279" class="Symbol">(</a><a name="1280" href="#1236" class="Bound">B</a><a name="1281"> </a><a name="1282" href="#1264" class="Bound">x</a><a name="1283" class="Symbol">))</a><a name="1285">
</a><a name="1295" class="Symbol">→</a><a name="1296"> </a><a name="1297" href="" class="Function">contr</a><a name="1302"> </a><a name="1303" class="Symbol">((</a><a name="1305" href="#1305" class="Bound">x</a><a name="1306"> </a><a name="1307" class="Symbol">:</a><a name="1308"> </a><a name="1309" href="#1225" class="Bound">A</a><a name="1310" class="Symbol">)</a><a name="1311"> </a><a name="1312" class="Symbol">→</a><a name="1313"> </a><a name="1314" href="#1236" class="Bound">B</a><a name="1315"> </a><a name="1316" href="#1305" class="Bound">x</a><a name="1317" class="Symbol">)</a></code></pre>
<h3 id="wfep-implies-function-extensionality">WFEP implies function extensionality</h3>
<p>Showing that WFEP implies function extensionality does not need univalence, and is quite straightforward. First, we define what we mean by function extensionality:</p>
<pre class="Agda"><code><a name="1552" href="#1552" class="Function">Funext</a><a name="1558"> </a><a name="1559" class="Symbol">:</a><a name="1560"> </a><a name="1561" class="Symbol">∀</a><a name="1562"> </a><a name="1563" href="#1563" class="Bound">i</a><a name="1564"> </a><a name="1565" href="#1565" class="Bound">j</a><a name="1566"> </a><a name="1567" class="Symbol">→</a><a name="1568"> </a><a name="1569" class="PrimitiveType">Set</a><a name="1572"> </a><a name="1573" class="Symbol">_</a><a name="1574">
</a><a name="1575" href="#1552" class="Function">Funext</a><a name="1581"> </a><a name="1582" href="#1582" class="Bound">i</a><a name="1583"> </a><a name="1584" href="#1584" class="Bound">j</a><a name="1585"> </a><a name="1586" class="Symbol">=</a><a name="1587"> </a><a name="1588" class="Symbol">{</a><a name="1589" href="#1589" class="Bound">A</a><a name="1590"> </a><a name="1591" class="Symbol">:</a><a name="1592"> </a><a name="1593" class="PrimitiveType">Set</a><a name="1596"> </a><a name="1597" href="#1582" class="Bound">i</a><a name="1598" class="Symbol">}{</a><a name="1600" href="#1600" class="Bound">B</a><a name="1601"> </a><a name="1602" class="Symbol">:</a><a name="1603"> </a><a name="1604" href="#1589" class="Bound">A</a><a name="1605"> </a><a name="1606" class="Symbol">→</a><a name="1607"> </a><a name="1608" class="PrimitiveType">Set</a><a name="1611"> </a><a name="1612" href="#1584" class="Bound">j</a><a name="1613" class="Symbol">}</a><a name="1614">
</a><a name="1626" class="Symbol">→</a><a name="1627"> </a><a name="1628" class="Symbol">{</a><a name="1629" href="#1629" class="Bound">f</a><a name="1630"> </a><a name="1631" href="#1631" class="Bound">g</a><a name="1632"> </a><a name="1633" class="Symbol">:</a><a name="1634"> </a><a name="1635" class="Symbol">(</a><a name="1636" href="#1636" class="Bound">x</a><a name="1637"> </a><a name="1638" class="Symbol">:</a><a name="1639"> </a><a name="1640" href="#1589" class="Bound">A</a><a name="1641" class="Symbol">)</a><a name="1642"> </a><a name="1643" class="Symbol">→</a><a name="1644"> </a><a name="1645" href="#1600" class="Bound">B</a><a name="1646"> </a><a name="1647" href="#1636" class="Bound">x</a><a name="1648" class="Symbol">}</a><a name="1649">
</a><a name="1661" class="Symbol">→</a><a name="1662"> </a><a name="1663" class="Symbol">((</a><a name="1665" href="#1665" class="Bound">x</a><a name="1666"> </a><a name="1667" class="Symbol">:</a><a name="1668"> </a><a name="1669" href="#1589" class="Bound">A</a><a name="1670" class="Symbol">)</a><a name="1671"> </a><a name="1672" class="Symbol">→</a><a name="1673"> </a><a name="1674" href="#1629" class="Bound">f</a><a name="1675"> </a><a name="1676" href="#1665" class="Bound">x</a><a name="1677"> </a><a name="1678" href="" class="Datatype Operator">≡</a><a name="1679"> </a><a name="1680" href="#1631" class="Bound">g</a><a name="1681"> </a><a name="1682" href="#1665" class="Bound">x</a><a name="1683" class="Symbol">)</a><a name="1684">
</a><a name="1696" class="Symbol">→</a><a name="1697"> </a><a name="1698" href="#1629" class="Bound">f</a><a name="1699"> </a><a name="1700" href="" class="Datatype Operator">≡</a><a name="1701"> </a><a name="1702" href="#1631" class="Bound">g</a></code></pre>
<p>Now we want to show the following:</p>
<pre class="Agda"><code><a name="1765" href="#1765" class="Function">wfep-to-funext</a><a name="1779"> </a><a name="1780" class="Symbol">:</a><a name="1781"> </a><a name="1782" class="Symbol">∀</a><a name="1783"> </a><a name="1784" class="Symbol">{</a><a name="1785" href="#1785" class="Bound">i</a><a name="1786" class="Symbol">}{</a><a name="1788" href="#1788" class="Bound">j</a><a name="1789" class="Symbol">}</a><a name="1790"> </a><a name="1791" class="Symbol">→</a><a name="1792"> </a><a name="1793" href="#1192" class="Function">WFEP</a><a name="1797"> </a><a name="1798" href="#1785" class="Bound">i</a><a name="1799"> </a><a name="1800" href="#1788" class="Bound">j</a><a name="1801"> </a><a name="1802" class="Symbol">→</a><a name="1803"> </a><a name="1804" href="#1552" class="Function">Funext</a><a name="1810"> </a><a name="1811" href="#1785" class="Bound">i</a><a name="1812"> </a><a name="1813" href="#1788" class="Bound">j</a><a name="1814">
</a><a name="1815" href="#1765" class="Function">wfep-to-funext</a><a name="1829"> </a><a name="1830" class="Symbol">{</a><a name="1831" href="#1831" class="Bound">i</a><a name="1832" class="Symbol">}{</a><a name="1834" href="#1834" class="Bound">j</a><a name="1835" class="Symbol">}</a><a name="1836"> </a><a name="1837" href="#1837" class="Bound">wfep</a><a name="1841"> </a><a name="1842" class="Symbol">{</a><a name="1843" href="#1843" class="Bound">A</a><a name="1844" class="Symbol">}{</a><a name="1846" href="#1846" class="Bound">B</a><a name="1847" class="Symbol">}{</a><a name="1849" href="#1849" class="Bound">f</a><a name="1850" class="Symbol">}{</a><a name="1852" href="#1852" class="Bound">g</a><a name="1853" class="Symbol">}</a><a name="1854"> </a><a name="1855" href="#1855" class="Bound">h</a><a name="1856"> </a><a name="1857" class="Symbol">=</a><a name="1858"> </a><a name="1859" href="#2784" class="Function">p</a><a name="1860">
</a><a name="1863" class="Keyword">where</a></code></pre>
<p>To prove that <span class="math">\(f\)</span> and <span class="math">\(g\)</span> are equal, we show that they both have values in the following dependent type, which we can think of as a subtype of <span class="math">\(B(x)\)</span> for all <span class="math">\(x : A\)</span>:</p>
<pre class="Agda"><code><a name="2047"> </a><a name="2066" href="#2066" class="Function">C</a><a name="2067"> </a><a name="2068" class="Symbol">:</a><a name="2069"> </a><a name="2070" href="#1843" class="Bound">A</a><a name="2071"> </a><a name="2072" class="Symbol">→</a><a name="2073"> </a><a name="2074" class="PrimitiveType">Set</a><a name="2077"> </a><a name="2078" href="#1834" class="Bound">j</a><a name="2079">
</a><a name="2084" href="#2066" class="Function">C</a><a name="2085"> </a><a name="2086" href="#2086" class="Bound">x</a><a name="2087"> </a><a name="2088" class="Symbol">=</a><a name="2089"> </a><a name="2090" href="" class="Record">Σ</a><a name="2091"> </a><a name="2092" class="Symbol">(</a><a name="2093" href="#1846" class="Bound">B</a><a name="2094"> </a><a name="2095" href="#2086" class="Bound">x</a><a name="2096" class="Symbol">)</a><a name="2097"> </a><a name="2098" class="Symbol">λ</a><a name="2099"> </a><a name="2100" href="#2100" class="Bound">y</a><a name="2101"> </a><a name="2102" class="Symbol">→</a><a name="2103"> </a><a name="2104" href="#1849" class="Bound">f</a><a name="2105"> </a><a name="2106" href="#2086" class="Bound">x</a><a name="2107"> </a><a name="2108" href="" class="Datatype Operator">≡</a><a name="2109"> </a><a name="2110" href="#2100" class="Bound">y</a></code></pre>
<p>We denote by <span class="math">\(f'\)</span> and <span class="math">\(g'\)</span> the range restrictions of <span class="math">\(f\)</span> and <span class="math">\(g\)</span> to <span class="math">\(C\)</span>:</p>
<pre class="Agda"><code><a name="2196"> </a><a name="2215" href="#2215" class="Function">f'</a><a name="2217"> </a><a name="2218" href="#2218" class="Function">g'</a><a name="2220"> </a><a name="2221" class="Symbol">:</a><a name="2222"> </a><a name="2223" class="Symbol">(</a><a name="2224" href="#2224" class="Bound">x</a><a name="2225"> </a><a name="2226" class="Symbol">:</a><a name="2227"> </a><a name="2228" href="#1843" class="Bound">A</a><a name="2229" class="Symbol">)</a><a name="2230"> </a><a name="2231" class="Symbol">→</a><a name="2232"> </a><a name="2233" href="#2066" class="Function">C</a><a name="2234"> </a><a name="2235" href="#2224" class="Bound">x</a><a name="2236">
</a><a name="2241" href="#2215" class="Function">f'</a><a name="2243"> </a><a name="2244" href="#2244" class="Bound">x</a><a name="2245"> </a><a name="2246" class="Symbol">=</a><a name="2247"> </a><a name="2248" class="Symbol">(</a><a name="2249" href="#1849" class="Bound">f</a><a name="2250"> </a><a name="2251" href="#2244" class="Bound">x</a><a name="2252"> </a><a name="2253" href="" class="InductiveConstructor Operator">,</a><a name="2254"> </a><a name="2255" href="" class="InductiveConstructor">refl</a><a name="2259" class="Symbol">)</a><a name="2260">
</a><a name="2265" href="#2218" class="Function">g'</a><a name="2267"> </a><a name="2268" href="#2268" class="Bound">x</a><a name="2269"> </a><a name="2270" class="Symbol">=</a><a name="2271"> </a><a name="2272" class="Symbol">(</a><a name="2273" href="#1852" class="Bound">g</a><a name="2274"> </a><a name="2275" href="#2268" class="Bound">x</a><a name="2276"> </a><a name="2277" href="" class="InductiveConstructor Operator">,</a><a name="2278"> </a><a name="2279" href="#1855" class="Bound">h</a><a name="2280"> </a><a name="2281" href="#2268" class="Bound">x</a><a name="2282" class="Symbol">)</a></code></pre>
<p>where we made use of the homotopy <span class="math">\(h\)</span> between <span class="math">\(f\)</span> and <span class="math">\(g\)</span> to show that <span class="math">\(g\)</span> has values in <span class="math">\(C\)</span>. Now, <span class="math">\(C(x)\)</span> is a singleton for all <span class="math">\(x : A\)</span>, so, by WFEP, <span class="math">\(f'\)</span> and <span class="math">\(g'\)</span> have the same contractible type, hence they are equal:</p>
<pre class="Agda"><code><a name="2516"> </a><a name="2535" href="#2535" class="Function">p'</a><a name="2537"> </a><a name="2538" class="Symbol">:</a><a name="2539"> </a><a name="2540" href="#2215" class="Function">f'</a><a name="2542"> </a><a name="2543" href="" class="Datatype Operator">≡</a><a name="2544"> </a><a name="2545" href="#2218" class="Function">g'</a><a name="2547">
</a><a name="2552" href="#2535" class="Function">p'</a><a name="2554"> </a><a name="2555" class="Symbol">=</a><a name="2556"> </a><a name="2557" href="" class="Function">contr⇒prop</a><a name="2567"> </a><a name="2568" class="Symbol">(</a><a name="2569" href="#1837" class="Bound">wfep</a><a name="2573"> </a><a name="2574" class="Symbol">(λ</a><a name="2576"> </a><a name="2577" href="#2577" class="Bound">x</a><a name="2578"> </a><a name="2579" class="Symbol">→</a><a name="2580"> </a><a name="2581" href="" class="Function">singl-contr</a><a name="2592"> </a><a name="2593" class="Symbol">(</a><a name="2594" href="#1849" class="Bound">f</a><a name="2595"> </a><a name="2596" href="#2577" class="Bound">x</a><a name="2597" class="Symbol">)))</a><a name="2600"> </a><a name="2601" href="#2215" class="Function">f'</a><a name="2603"> </a><a name="2604" href="#2218" class="Function">g'</a></code></pre>
<p>The fact that <span class="math">\(f\)</span> and <span class="math">\(g\)</span> are equal then follows immediately by applying the first projection and (implicitly) using <span class="math">\(η\)</span> conversion for <span class="math">\(Π\)</span>-types:</p>
<pre class="Agda"><code><a name="2765"> </a><a name="2784" href="#2784" class="Function">p</a><a name="2785"> </a><a name="2786" class="Symbol">:</a><a name="2787"> </a><a name="2788" href="#1849" class="Bound">f</a><a name="2789"> </a><a name="2790" href="" class="Datatype Operator">≡</a><a name="2791"> </a><a name="2792" href="#1852" class="Bound">g</a><a name="2793">
</a><a name="2798" href="#2784" class="Function">p</a><a name="2799"> </a><a name="2800" class="Symbol">=</a><a name="2801"> </a><a name="2802" href="" class="Function">ap</a><a name="2804"> </a><a name="2805" class="Symbol">(λ</a><a name="2807"> </a><a name="2808" href="#2808" class="Bound">u</a><a name="2809"> </a><a name="2810" href="#2810" class="Bound">x</a><a name="2811"> </a><a name="2812" class="Symbol">→</a><a name="2813"> </a><a name="2814" href="" class="Function">proj₁</a><a name="2819"> </a><a name="2820" class="Symbol">(</a><a name="2821" href="#2808" class="Bound">u</a><a name="2822"> </a><a name="2823" href="#2810" class="Bound">x</a><a name="2824" class="Symbol">))</a><a name="2826"> </a><a name="2827" href="#2535" class="Function">p'</a></code></pre>
<p>In the book, the strong version of extensionality, i.e.</p>
<pre class="Agda"><code><a name="2912" href="#2912" class="Function">StrongFunext</a><a name="2924"> </a><a name="2925" class="Symbol">:</a><a name="2926"> </a><a name="2927" class="Symbol">∀</a><a name="2928"> </a><a name="2929" href="#2929" class="Bound">i</a><a name="2930"> </a><a name="2931" href="#2931" class="Bound">j</a><a name="2932"> </a><a name="2933" class="Symbol">→</a><a name="2934"> </a><a name="2935" class="PrimitiveType">Set</a><a name="2938"> </a><a name="2939" class="Symbol">_</a><a name="2940">
</a><a name="2941" href="#2912" class="Function">StrongFunext</a><a name="2953"> </a><a name="2954" href="#2954" class="Bound">i</a><a name="2955"> </a><a name="2956" href="#2956" class="Bound">j</a><a name="2957"> </a><a name="2958" class="Symbol">=</a><a name="2959"> </a><a name="2960" class="Symbol">{</a><a name="2961" href="#2961" class="Bound">A</a><a name="2962"> </a><a name="2963" class="Symbol">:</a><a name="2964"> </a><a name="2965" class="PrimitiveType">Set</a><a name="2968"> </a><a name="2969" href="#2954" class="Bound">i</a><a name="2970" class="Symbol">}{</a><a name="2972" href="#2972" class="Bound">B</a><a name="2973"> </a><a name="2974" class="Symbol">:</a><a name="2975"> </a><a name="2976" href="#2961" class="Bound">A</a><a name="2977"> </a><a name="2978" class="Symbol">→</a><a name="2979"> </a><a name="2980" class="PrimitiveType">Set</a><a name="2983"> </a><a name="2984" href="#2956" class="Bound">j</a><a name="2985" class="Symbol">}</a><a name="2986">
</a><a name="3004" class="Symbol">→</a><a name="3005"> </a><a name="3006" class="Symbol">{</a><a name="3007" href="#3007" class="Bound">f</a><a name="3008"> </a><a name="3009" href="#3009" class="Bound">g</a><a name="3010"> </a><a name="3011" class="Symbol">:</a><a name="3012"> </a><a name="3013" class="Symbol">(</a><a name="3014" href="#3014" class="Bound">x</a><a name="3015"> </a><a name="3016" class="Symbol">:</a><a name="3017"> </a><a name="3018" href="#2961" class="Bound">A</a><a name="3019" class="Symbol">)</a><a name="3020"> </a><a name="3021" class="Symbol">→</a><a name="3022"> </a><a name="3023" href="#2972" class="Bound">B</a><a name="3024"> </a><a name="3025" href="#3014" class="Bound">x</a><a name="3026" class="Symbol">}</a><a name="3027">
</a><a name="3045" class="Symbol">→</a><a name="3046"> </a><a name="3047" class="Symbol">((</a><a name="3049" href="#3049" class="Bound">x</a><a name="3050"> </a><a name="3051" class="Symbol">:</a><a name="3052"> </a><a name="3053" href="#2961" class="Bound">A</a><a name="3054" class="Symbol">)</a><a name="3055"> </a><a name="3056" class="Symbol">→</a><a name="3057"> </a><a name="3058" href="#3007" class="Bound">f</a><a name="3059"> </a><a name="3060" href="#3049" class="Bound">x</a><a name="3061"> </a><a name="3062" href="" class="Datatype Operator">≡</a><a name="3063"> </a><a name="3064" href="#3009" class="Bound">g</a><a name="3065"> </a><a name="3066" href="#3049" class="Bound">x</a><a name="3067" class="Symbol">)</a><a name="3068">
</a><a name="3086" href="" class="Record Operator">≅</a><a name="3087"> </a><a name="3088" class="Symbol">(</a><a name="3089" href="#3007" class="Bound">f</a><a name="3090"> </a><a name="3091" href="" class="Datatype Operator">≡</a><a name="3092"> </a><a name="3093" href="#3009" class="Bound">g</a><a name="3094" class="Symbol">)</a></code></pre>
<p>is obtained directly using a more sophisticated, but very similar argument.</p>
<h3 id="proving-wfep">Proving WFEP</h3>
<p>Now we turn to proving WFEP itself. Most of the proofs I know use the fact that univalence implies a certain congruence rule for function-types, i.e. if <span class="math">\(B\)</span> and <span class="math">\(B'\)</span> are equivalent types, then <span class="math">\(A → B\)</span> and <span class="math">\(A → B'\)</span> are also equivalent, and furthermore the equivalence is given by precomposing with the equivalence between <span class="math">\(B\)</span> and <span class="math">\(B'\)</span>.</p>
<p>However, if we have η conversion for record types, there is a much simpler way to obtain WFEP from univalence.</p>
<p>The idea is as follows: since <span class="math">\(B(x)\)</span> is contractible for all <span class="math">\(x : A\)</span>, univalence implies that <span class="math">\(B(x) ≡ ⊤\)</span>, so the contractibility of <span class="math">\((x : A) → B(x)\)</span> is a consequence of the contractibility of <span class="math">\(A → ⊤\)</span>, which is itself an immediate consequence of the <a class="target" id="contr-exp-T">definitional <span class="math">\(η\)</span> rule for <span class="math">\(⊤\)</span></a>:</p>
<pre class="Agda"><code><a name="4029"></a><a name="4032" class="Keyword">record</a><a name="4038"> </a><a name="4039" href="#4039" class="Record">⊤</a><a name="4040"> </a><a name="4041" class="Symbol">:</a><a name="4042"> </a><a name="4043" class="PrimitiveType">Set</a><a name="4046"> </a><a name="4047" href="#4009" class="Bound">j</a><a name="4048"> </a><a name="4049" class="Keyword">where</a><a name="4054">
</a><a name="4059" class="Keyword">constructor</a><a name="4070"> </a><a name="4071" href="#4071" class="InductiveConstructor">tt</a><a name="4073">
</a><a name="4077" href="#4077" class="Function">⊤-contr</a><a name="4084"> </a><a name="4085" class="Symbol">:</a><a name="4086"> </a><a name="4087" href="" class="Function">contr</a><a name="4092"> </a><a name="4093" href="#4039" class="Record">⊤</a><a name="4094">
</a><a name="4097" href="#4077" class="Function">⊤-contr</a><a name="4104"> </a><a name="4105" class="Symbol">=</a><a name="4106"> </a><a name="4107" href="#4071" class="InductiveConstructor">tt</a><a name="4109"> </a><a name="4110" href="" class="InductiveConstructor Operator">,</a><a name="4111"> </a><a name="4112" class="Symbol">λ</a><a name="4113"> </a><a name="4114" class="Symbol">{</a><a name="4115"> </a><a name="4116" href="#4071" class="InductiveConstructor">tt</a><a name="4118"> </a><a name="4119" class="Symbol">→</a><a name="4120"> </a><a name="4121" href="" class="InductiveConstructor">refl</a><a name="4125"> </a><a name="4126" class="Symbol">}</a><a name="4127">
</a><a name="4131" href="#4131" class="Function">contr-exp-⊤</a><a name="4142"> </a><a name="4143" class="Symbol">:</a><a name="4144"> </a><a name="4145" class="Symbol">∀</a><a name="4146"> </a><a name="4147" class="Symbol">{</a><a name="4148" href="#4148" class="Bound">i</a><a name="4149" class="Symbol">}{</a><a name="4151" href="#4151" class="Bound">A</a><a name="4152"> </a><a name="4153" class="Symbol">:</a><a name="4154"> </a><a name="4155" class="PrimitiveType">Set</a><a name="4158"> </a><a name="4159" href="#4148" class="Bound">i</a><a name="4160" class="Symbol">}</a><a name="4161"> </a><a name="4162" class="Symbol">→</a><a name="4163"> </a><a name="4164" href="" class="Function">contr</a><a name="4169"> </a><a name="4170" class="Symbol">(</a><a name="4171" href="#4151" class="Bound">A</a><a name="4172"> </a><a name="4173" class="Symbol">→</a><a name="4174"> </a><a name="4175" href="#4039" class="Record">⊤</a><a name="4176" class="Symbol">)</a><a name="4177">
</a><a name="4180" href="#4131" class="Function">contr-exp-⊤</a><a name="4191"> </a><a name="4192" class="Symbol">=</a><a name="4193"> </a><a name="4194" class="Symbol">(λ</a><a name="4196"> </a><a name="4197" href="#4197" class="Bound">_</a><a name="4198"> </a><a name="4199" class="Symbol">→</a><a name="4200"> </a><a name="4201" href="#4071" class="InductiveConstructor">tt</a><a name="4203" class="Symbol">)</a><a name="4204"> </a><a name="4205" href="" class="InductiveConstructor Operator">,</a><a name="4206"> </a><a name="4207" class="Symbol">(λ</a><a name="4209"> </a><a name="4210" href="#4210" class="Bound">f</a><a name="4211"> </a><a name="4212" class="Symbol">→</a><a name="4213"> </a><a name="4214" href="" class="InductiveConstructor">refl</a><a name="4218" class="Symbol">)</a><a name="4219">
<p>However, the proof sketch above is missing a crucial step: even though <span class="math">\(B(x)\)</span> is pointwise equal to <span class="math">\(⊤\)</span>, in order to substitute <span class="math">\(⊤\)</span> for <span class="math">\(B(x)\)</span> in the <span class="math">\(Π\)</span>-type, we need to show that <span class="math">\(B ≡ λ \_ → ⊤\)</span>, but we’re not allowed to use function extensionality, yet!</p>
<p>Fortunately, we only need a very special case of function extensionality. So the trick here is to apply the argument to this special case first, and then use it to prove the general result.</p>
<p>First we prove WFEP for non-dependent <span class="math">\(Π\)</span>-types, by formalising the above proof sketch.</p>
<pre class="Agda"><code><a name="4794" href="#4794" class="Function">nondep-wfep</a><a name="4805"> </a><a name="4806" class="Symbol">:</a><a name="4807"> </a><a name="4808" class="Symbol">∀</a><a name="4809"> </a><a name="4810" class="Symbol">{</a><a name="4811" href="#4811" class="Bound">i</a><a name="4812"> </a><a name="4813" href="#4813" class="Bound">j</a><a name="4814" class="Symbol">}{</a><a name="4816" href="#4816" class="Bound">A</a><a name="4817"> </a><a name="4818" class="Symbol">:</a><a name="4819"> </a><a name="4820" class="PrimitiveType">Set</a><a name="4823"> </a><a name="4824" href="#4811" class="Bound">i</a><a name="4825" class="Symbol">}{</a><a name="4827" href="#4827" class="Bound">B</a><a name="4828"> </a><a name="4829" class="Symbol">:</a><a name="4830"> </a><a name="4831" class="PrimitiveType">Set</a><a name="4834"> </a><a name="4835" href="#4813" class="Bound">j</a><a name="4836" class="Symbol">}</a><a name="4837">
</a><a name="4850" class="Symbol">→</a><a name="4851"> </a><a name="4852" href="" class="Function">contr</a><a name="4857"> </a><a name="4858" href="#4827" class="Bound">B</a><a name="4859">
</a><a name="4872" class="Symbol">→</a><a name="4873"> </a><a name="4874" href="" class="Function">contr</a><a name="4879"> </a><a name="4880" class="Symbol">(</a><a name="4881" href="#4816" class="Bound">A</a><a name="4882"> </a><a name="4883" class="Symbol">→</a><a name="4884"> </a><a name="4885" href="#4827" class="Bound">B</a><a name="4886" class="Symbol">)</a><a name="4887">
</a><a name="4888" href="#4794" class="Function">nondep-wfep</a><a name="4899"> </a><a name="4900" class="Symbol">{</a><a name="4901">A </a><a name="4903" class="Symbol">=</a><a name="4904"> </a><a name="4905" href="#4905" class="Bound">A</a><a name="4906" class="Symbol">}{</a><a name="4908">B </a><a name="4910" class="Symbol">=</a><a name="4911"> </a><a name="4912" href="#4912" class="Bound">B</a><a name="4913" class="Symbol">}</a><a name="4914"> </a><a name="4915" href="#4915" class="Bound">hB</a><a name="4917"> </a><a name="4918" class="Symbol">=</a><a name="4919"> </a><a name="4920" href="" class="Function">subst</a><a name="4925"> </a><a name="4926" href="" class="Function">contr</a><a name="4931"> </a><a name="4932" href="#4992" class="Function">p</a><a name="4933"> </a><a name="4934" href="#4131" class="Function">contr-exp-⊤</a><a name="4945">
</a><a name="4948" class="Keyword">where</a><a name="4953">
</a><a name="4987"> </a><a name="4992" href="#4992" class="Function">p</a><a name="4993"> </a><a name="4994" class="Symbol">:</a><a name="4995"> </a><a name="4996" class="Symbol">(</a><a name="4997" href="#4905" class="Bound">A</a><a name="4998"> </a><a name="4999" class="Symbol">→</a><a name="5000"> </a><a name="5001" href="#4039" class="Record">⊤</a><a name="5002" class="Symbol">)</a><a name="5003"> </a><a name="5004" href="" class="Datatype Operator">≡</a><a name="5005"> </a><a name="5006" class="Symbol">(</a><a name="5007" href="#4905" class="Bound">A</a><a name="5008"> </a><a name="5009" class="Symbol">→</a><a name="5010"> </a><a name="5011" href="#4912" class="Bound">B</a><a name="5012" class="Symbol">)</a><a name="5013">
</a><a name="5018" href="#4992" class="Function">p</a><a name="5019"> </a><a name="5020" class="Symbol">=</a><a name="5021"> </a><a name="5022" href="" class="Function">ap</a><a name="5024"> </a><a name="5025" class="Symbol">(λ</a><a name="5027"> </a><a name="5028" href="#5028" class="Bound">X</a><a name="5029"> </a><a name="5030" class="Symbol">→</a><a name="5031"> </a><a name="5032" href="#4905" class="Bound">A</a><a name="5033"> </a><a name="5034" class="Symbol">→</a><a name="5035"> </a><a name="5036" href="#5028" class="Bound">X</a><a name="5037" class="Symbol">)</a><a name="5038"> </a><a name="5039" class="Symbol">(</a><a name="5040" href="" class="Function">unique-contr</a><a name="5052"> </a><a name="5053" href="#4077" class="Function">⊤-contr</a><a name="5060"> </a><a name="5061" href="#4915" class="Bound">hB</a><a name="5063" class="Symbol">)</a></code></pre>
<p>Since <span class="math">\(B\)</span> is non-dependent in this case, the proof goes through without function extensionality, so we don’t get stuck in an infinite regression: two iterations are enough!</p>
<p>Now we can prove the special case of function extensionality that we will need for the proof of full WFEP:</p>
<pre class="Agda"><code><a name="5372" href="#5372" class="Function">funext'</a><a name="5379"> </a><a name="5380" class="Symbol">:</a><a name="5381"> </a><a name="5382" class="Symbol">∀</a><a name="5383"> </a><a name="5384" class="Symbol">{</a><a name="5385" href="#5385" class="Bound">i</a><a name="5386"> </a><a name="5387" href="#5387" class="Bound">j</a><a name="5388" class="Symbol">}{</a><a name="5390" href="#5390" class="Bound">A</a><a name="5391"> </a><a name="5392" class="Symbol">:</a><a name="5393"> </a><a name="5394" class="PrimitiveType">Set</a><a name="5397"> </a><a name="5398" href="#5385" class="Bound">i</a><a name="5399" class="Symbol">}{</a><a name="5401" href="#5401" class="Bound">B</a><a name="5402"> </a><a name="5403" class="Symbol">:</a><a name="5404"> </a><a name="5405" class="PrimitiveType">Set</a><a name="5408"> </a><a name="5409" href="#5387" class="Bound">j</a><a name="5410" class="Symbol">}</a><a name="5411">
</a><a name="5420" class="Symbol">→</a><a name="5421"> </a><a name="5422" class="Symbol">(</a><a name="5423" href="#5423" class="Bound">f</a><a name="5424"> </a><a name="5425" class="Symbol">:</a><a name="5426"> </a><a name="5427" href="#5390" class="Bound">A</a><a name="5428"> </a><a name="5429" class="Symbol">→</a><a name="5430"> </a><a name="5431" href="#5401" class="Bound">B</a><a name="5432" class="Symbol">)(</a><a name="5434" href="#5434" class="Bound">b</a><a name="5435"> </a><a name="5436" class="Symbol">:</a><a name="5437"> </a><a name="5438" href="#5401" class="Bound">B</a><a name="5439" class="Symbol">)(</a><a name="5441" href="#5441" class="Bound">h</a><a name="5442"> </a><a name="5443" class="Symbol">:</a><a name="5444"> </a><a name="5445" class="Symbol">(</a><a name="5446" href="#5446" class="Bound">x</a><a name="5447"> </a><a name="5448" class="Symbol">:</a><a name="5449"> </a><a name="5450" href="#5390" class="Bound">A</a><a name="5451" class="Symbol">)</a><a name="5452"> </a><a name="5453" class="Symbol">→</a><a name="5454"> </a><a name="5455" href="#5434" class="Bound">b</a><a name="5456"> </a><a name="5457" href="" class="Datatype Operator">≡</a><a name="5458"> </a><a name="5459" href="#5423" class="Bound">f</a><a name="5460"> </a><a name="5461" href="#5446" class="Bound">x</a><a name="5462" class="Symbol">)</a><a name="5463">
</a><a name="5472" class="Symbol">→</a><a name="5473"> </a><a name="5474" class="Symbol">(λ</a><a name="5476"> </a><a name="5477" href="#5477" class="Bound">_</a><a name="5478"> </a><a name="5479" class="Symbol">→</a><a name="5480"> </a><a name="5481" href="#5434" class="Bound">b</a><a name="5482" class="Symbol">)</a><a name="5483"> </a><a name="5484" href="" class="Datatype Operator">≡</a><a name="5485"> </a><a name="5486" href="#5423" class="Bound">f</a><a name="5487">
</a><a name="5488" href="#5372" class="Function">funext'</a><a name="5495"> </a><a name="5496" href="#5496" class="Bound">f</a><a name="5497"> </a><a name="5498" href="#5498" class="Bound">b</a><a name="5499"> </a><a name="5500" href="#5500" class="Bound">h</a><a name="5501"> </a><a name="5502" class="Symbol">=</a><a name="5503">
</a><a name="5506" href="" class="Function">ap</a><a name="5508"> </a><a name="5509" class="Symbol">(λ</a><a name="5511"> </a><a name="5512" href="#5512" class="Bound">u</a><a name="5513"> </a><a name="5514" href="#5514" class="Bound">x</a><a name="5515"> </a><a name="5516" class="Symbol">→</a><a name="5517"> </a><a name="5518" href="" class="Function">proj₁</a><a name="5523"> </a><a name="5524" class="Symbol">(</a><a name="5525" href="#5512" class="Bound">u</a><a name="5526"> </a><a name="5527" href="#5514" class="Bound">x</a><a name="5528" class="Symbol">))</a><a name="5530">
</a><a name="5538" class="Symbol">(</a><a name="5539" href="" class="Function">contr⇒prop</a><a name="5549"> </a><a name="5550" class="Symbol">(</a><a name="5551" href="#4794" class="Function">nondep-wfep</a><a name="5562"> </a><a name="5563" class="Symbol">(</a><a name="5564" href="" class="Function">singl-contr</a><a name="5575"> </a><a name="5576" href="#5498" class="Bound">b</a><a name="5577" class="Symbol">))</a><a name="5579">
</a><a name="5600" class="Symbol">(λ</a><a name="5602"> </a><a name="5603" href="#5603" class="Bound">_</a><a name="5604"> </a><a name="5605" class="Symbol">→</a><a name="5606"> </a><a name="5607" class="Symbol">(</a><a name="5608" href="#5498" class="Bound">b</a><a name="5609"> </a><a name="5610" href="" class="InductiveConstructor Operator">,</a><a name="5611"> </a><a name="5612" href="" class="InductiveConstructor">refl</a><a name="5616" class="Symbol">))</a><a name="5618">
</a><a name="5639" class="Symbol">(λ</a><a name="5641"> </a><a name="5642" href="#5642" class="Bound">x</a><a name="5643"> </a><a name="5644" class="Symbol">→</a><a name="5645"> </a><a name="5646" href="#5496" class="Bound">f</a><a name="5647"> </a><a name="5648" href="#5642" class="Bound">x</a><a name="5649"> </a><a name="5650" href="" class="InductiveConstructor Operator">,</a><a name="5651"> </a><a name="5652" href="#5500" class="Bound">h</a><a name="5653"> </a><a name="5654" href="#5642" class="Bound">x</a><a name="5655" class="Symbol">))</a></code></pre>
<p>Same proof as for <code>wfep-to-funext</code>, only written more succinctly.</p>
<p>Finally, we are ready to prove WFEP:</p>
<pre class="Agda"><code><a name="5788" href="#5788" class="Function">wfep</a><a name="5792"> </a><a name="5793" class="Symbol">:</a><a name="5794"> </a><a name="5795" class="Symbol">∀</a><a name="5796"> </a><a name="5797" class="Symbol">{</a><a name="5798" href="#5798" class="Bound">i</a><a name="5799"> </a><a name="5800" href="#5800" class="Bound">j</a><a name="5801" class="Symbol">}</a><a name="5802"> </a><a name="5803" class="Symbol">→</a><a name="5804"> </a><a name="5805" href="#1192" class="Function">WFEP</a><a name="5809"> </a><a name="5810" href="#5798" class="Bound">i</a><a name="5811"> </a><a name="5812" href="#5800" class="Bound">j</a><a name="5813">
</a><a name="5814" href="#5788" class="Function">wfep</a><a name="5818"> </a><a name="5819" class="Symbol">{</a><a name="5820" href="#5820" class="Bound">i</a><a name="5821" class="Symbol">}{</a><a name="5823" href="#5823" class="Bound">j</a><a name="5824" class="Symbol">}{</a><a name="5826" href="#5826" class="Bound">A</a><a name="5827" class="Symbol">}{</a><a name="5829" href="#5829" class="Bound">B</a><a name="5830" class="Symbol">}</a><a name="5831"> </a><a name="5832" href="#5832" class="Bound">hB</a><a name="5834"> </a><a name="5835" class="Symbol">=</a><a name="5836"> </a><a name="5837" href="" class="Function">subst</a><a name="5842"> </a><a name="5843" href="" class="Function">contr</a><a name="5848"> </a><a name="5849" href="#5990" class="Function">p</a><a name="5850"> </a><a name="5851" href="#4131" class="Function">contr-exp-⊤</a><a name="5862">
</a><a name="5865" class="Keyword">where</a><a name="5870">
</a><a name="5904"> </a><a name="5909" href="#5909" class="Function">p₀</a><a name="5911"> </a><a name="5912" class="Symbol">:</a><a name="5913"> </a><a name="5914" class="Symbol">(λ</a><a name="5916"> </a><a name="5917" href="#5917" class="Bound">_</a><a name="5918"> </a><a name="5919" class="Symbol">→</a><a name="5920"> </a><a name="5921" href="#4039" class="Record">⊤</a><a name="5922" class="Symbol">)</a><a name="5923"> </a><a name="5924" href="" class="Datatype Operator">≡</a><a name="5925"> </a><a name="5926" href="#5829" class="Bound">B</a><a name="5927">
</a><a name="5932" href="#5909" class="Function">p₀</a><a name="5934"> </a><a name="5935" class="Symbol">=</a><a name="5936"> </a><a name="5937" href="#5372" class="Function">funext'</a><a name="5944"> </a><a name="5945" href="#5829" class="Bound">B</a><a name="5946"> </a><a name="5947" href="#4039" class="Record">⊤</a><a name="5948"> </a><a name="5949" class="Symbol">(λ</a><a name="5951"> </a><a name="5952" href="#5952" class="Bound">x</a><a name="5953"> </a><a name="5954" class="Symbol">→</a><a name="5955"> </a><a name="5956" href="" class="Function">unique-contr</a><a name="5968"> </a><a name="5969" href="#4077" class="Function">⊤-contr</a><a name="5976"> </a><a name="5977" class="Symbol">(</a><a name="5978" href="#5832" class="Bound">hB</a><a name="5980"> </a><a name="5981" href="#5952" class="Bound">x</a><a name="5982" class="Symbol">))</a><a name="5984">
</a><a name="5990" href="#5990" class="Function">p</a><a name="5991"> </a><a name="5992" class="Symbol">:</a><a name="5993"> </a><a name="5994" class="Symbol">(</a><a name="5995" href="#5826" class="Bound">A</a><a name="5996"> </a><a name="5997" class="Symbol">→</a><a name="5998"> </a><a name="5999" href="#4039" class="Record">⊤</a><a name="6000"> </a><a name="6001" class="Symbol">{</a><a name="6002" href="#5823" class="Bound">j</a><a name="6003" class="Symbol">})</a><a name="6005"> </a><a name="6006" href="" class="Datatype Operator">≡</a><a name="6007"> </a><a name="6008" class="Symbol">((</a><a name="6010" href="#6010" class="Bound">x</a><a name="6011"> </a><a name="6012" class="Symbol">:</a><a name="6013"> </a><a name="6014" href="#5826" class="Bound">A</a><a name="6015" class="Symbol">)</a><a name="6016"> </a><a name="6017" class="Symbol">→</a><a name="6018"> </a><a name="6019" href="#5829" class="Bound">B</a><a name="6020"> </a><a name="6021" href="#6010" class="Bound">x</a><a name="6022" class="Symbol">)</a><a name="6023">
</a><a name="6028" href="#5990" class="Function">p</a><a name="6029"> </a><a name="6030" class="Symbol">=</a><a name="6031"> </a><a name="6032" href="" class="Function">ap</a><a name="6034"> </a><a name="6035" class="Symbol">(λ</a><a name="6037"> </a><a name="6038" href="#6038" class="Bound">Z</a><a name="6039"> </a><a name="6040" class="Symbol">→</a><a name="6041"> </a><a name="6042" class="Symbol">(</a><a name="6043" href="#6043" class="Bound">x</a><a name="6044"> </a><a name="6045" class="Symbol">:</a><a name="6046"> </a><a name="6047" href="#5826" class="Bound">A</a><a name="6048" class="Symbol">)</a><a name="6049"> </a><a name="6050" class="Symbol">→</a><a name="6051"> </a><a name="6052" href="#6038" class="Bound">Z</a><a name="6053"> </a><a name="6054" href="#6043" class="Bound">x</a><a name="6055" class="Symbol">)</a><a name="6056"> </a><a name="6057" href="#5909" class="Function">p₀</a></code></pre>
<p>By putting it all together we get function extensionality:</p>
<pre class="Agda"><code><a name="6145" href="#6145" class="Function">funext</a><a name="6151"> </a><a name="6152" class="Symbol">:</a><a name="6153"> </a><a name="6154" class="Symbol">∀</a><a name="6155"> </a><a name="6156" class="Symbol">{</a><a name="6157" href="#6157" class="Bound">i</a><a name="6158"> </a><a name="6159" href="#6159" class="Bound">j</a><a name="6160" class="Symbol">}</a><a name="6161"> </a><a name="6162" class="Symbol">→</a><a name="6163"> </a><a name="6164" href="#1552" class="Function">Funext</a><a name="6170"> </a><a name="6171" href="#6157" class="Bound">i</a><a name="6172"> </a><a name="6173" href="#6159" class="Bound">j</a><a name="6174">
</a><a name="6175" href="#6145" class="Function">funext</a><a name="6181"> </a><a name="6182" class="Symbol">=</a><a name="6183"> </a><a name="6184" href="#1765" class="Function">wfep-to-funext</a><a name="6198"> </a><a name="6199" href="#5788" class="Function">wfep</a></code></pre>
<h3 id="avoiding-η-for-records">Avoiding η for records</h3>
<p>This proof can also be modified to work in a theory where <span class="math">\(⊤\)</span> does not have definitional η conversion.</p>
<p>The only point where η is used is in the proof of <code>contr-exp-⊤</code> <a href="#contr-exp-T">above</a>. So let’s define a version of <span class="math">\(⊤\)</span> without η, and prove <code>contr-exp-⊤</code> for it.</p>
<pre class="Agda"><code><a name="6572"></a><a name="6575" class="Keyword">data</a><a name="6579"> </a><a name="6580" href="#6580" class="Datatype">⊤</a><a name="6581"> </a><a name="6582" class="Symbol">:</a><a name="6583"> </a><a name="6584" class="PrimitiveType">Set</a><a name="6587"> </a><a name="6588" href="#6552" class="Bound">j</a><a name="6589"> </a><a name="6590" class="Keyword">where</a><a name="6595">
</a><a name="6600" href="#6600" class="InductiveConstructor">tt</a><a name="6602"> </a><a name="6603" class="Symbol">:</a><a name="6604"> </a><a name="6605" href="#6580" class="Datatype">⊤</a><a name="6606">
</a><a name="6610" href="#6610" class="Function">⊤-contr</a><a name="6617"> </a><a name="6618" class="Symbol">:</a><a name="6619"> </a><a name="6620" href="" class="Function">contr</a><a name="6625"> </a><a name="6626" href="#6580" class="Datatype">⊤</a><a name="6627">
</a><a name="6630" href="#6610" class="Function">⊤-contr</a><a name="6637"> </a><a name="6638" class="Symbol">=</a><a name="6639"> </a><a name="6640" href="#6600" class="InductiveConstructor">tt</a><a name="6642"> </a><a name="6643" href="" class="InductiveConstructor Operator">,</a><a name="6644"> </a><a name="6645" class="Symbol">λ</a><a name="6646"> </a><a name="6647" class="Symbol">{</a><a name="6648"> </a><a name="6649" href="#6600" class="InductiveConstructor">tt</a><a name="6651"> </a><a name="6652" class="Symbol">→</a><a name="6653"> </a><a name="6654" href="" class="InductiveConstructor">refl</a><a name="6658"> </a><a name="6659" class="Symbol">}</a></code></pre>
<p>We begin by defining the automorphism <span class="math">\(k\)</span> of <span class="math">\(⊤\)</span> which maps everything to <span class="math">\(\mathsf{tt}\)</span>. Clearly, <span class="math">\(k\)</span> is going to be the identity, but we can’t prove that until we have function extensionality.</p>
<pre class="Agda"><code><a name="6867"></a><a name="6884" href="#6884" class="Function">k</a><a name="6885"> </a><a name="6886" class="Symbol">:</a><a name="6887"> </a><a name="6888" href="#6580" class="Datatype">⊤</a><a name="6889"> </a><a name="6890" class="Symbol">→</a><a name="6891"> </a><a name="6892" href="#6580" class="Datatype">⊤</a><a name="6893">
</a><a name="6896" href="#6884" class="Function">k</a><a name="6897"> </a><a name="6898" class="Symbol">_</a><a name="6899"> </a><a name="6900" class="Symbol">=</a><a name="6901"> </a><a name="6902" href="#6600" class="InductiveConstructor">tt</a><a name="6904">
</a><a name="6908" href="#6908" class="Function">k-we</a><a name="6912"> </a><a name="6913" class="Symbol">:</a><a name="6914"> </a><a name="6915" href="" class="Function">weak-equiv</a><a name="6925"> </a><a name="6926" href="#6884" class="Function">k</a><a name="6927">
</a><a name="6930" href="#6908" class="Function">k-we</a><a name="6934"> </a><a name="6935" href="#6600" class="InductiveConstructor">tt</a><a name="6937"> </a><a name="6938" class="Symbol">=</a><a name="6939"> </a><a name="6940" href="" class="Function">Σ-contr</a><a name="6947"> </a><a name="6948" href="#6610" class="Function">⊤-contr</a><a name="6955"> </a><a name="6956" class="Symbol">(λ</a><a name="6958"> </a><a name="6959" href="#6959" class="Bound">_</a><a name="6960"> </a><a name="6961" class="Symbol">→</a><a name="6962"> </a><a name="6963" href="" class="Function">h↑</a><a name="6965"> </a><a name="6966" href="#6610" class="Function">⊤-contr</a><a name="6973"> </a><a name="6974" href="#6600" class="InductiveConstructor">tt</a><a name="6976"> </a><a name="6977" href="#6600" class="InductiveConstructor">tt</a><a name="6979" class="Symbol">)</a></code></pre>
<p>Now we apply the argument sketched above, based on the fact that univalence implies congruence rules for function types. We extract an equality out of <span class="math">\(k\)</span>, and then transport it to the exponentials:</p>
<pre class="Agda"><code><a name="7192"></a><a name="7209" href="#7209" class="Function">k-eq</a><a name="7213"> </a><a name="7214" class="Symbol">:</a><a name="7215"> </a><a name="7216" href="#6580" class="Datatype">⊤</a><a name="7217"> </a><a name="7218" href="" class="Datatype Operator">≡</a><a name="7219"> </a><a name="7220" href="#6580" class="Datatype">⊤</a><a name="7221">
</a><a name="7224" href="#7209" class="Function">k-eq</a><a name="7228"> </a><a name="7229" class="Symbol">=</a><a name="7230"> </a><a name="7231" href="" class="Function">≈⇒≡</a><a name="7234"> </a><a name="7235" class="Symbol">(</a><a name="7236" href="#6884" class="Function">k</a><a name="7237"> </a><a name="7238" href="" class="InductiveConstructor Operator">,</a><a name="7239"> </a><a name="7240" href="#6908" class="Function">k-we</a><a name="7244" class="Symbol">)</a><a name="7245">
</a><a name="7249" href="#7249" class="Function">k-exp-eq</a><a name="7257"> </a><a name="7258" class="Symbol">:</a><a name="7259"> </a><a name="7260" class="Symbol">∀</a><a name="7261"> </a><a name="7262" class="Symbol">{</a><a name="7263" href="#7263" class="Bound">i</a><a name="7264" class="Symbol">}(</a><a name="7266" href="#7266" class="Bound">A</a><a name="7267"> </a><a name="7268" class="Symbol">:</a><a name="7269"> </a><a name="7270" class="PrimitiveType">Set</a><a name="7273"> </a><a name="7274" href="#7263" class="Bound">i</a><a name="7275" class="Symbol">)</a><a name="7276"> </a><a name="7277" class="Symbol">→</a><a name="7278"> </a><a name="7279" class="Symbol">(</a><a name="7280" href="#7266" class="Bound">A</a><a name="7281"> </a><a name="7282" class="Symbol">→</a><a name="7283"> </a><a name="7284" href="#6580" class="Datatype">⊤</a><a name="7285" class="Symbol">)</a><a name="7286"> </a><a name="7287" href="" class="Datatype Operator">≡</a><a name="7288"> </a><a name="7289" class="Symbol">(</a><a name="7290" href="#7266" class="Bound">A</a><a name="7291"> </a><a name="7292" class="Symbol">→</a><a name="7293"> </a><a name="7294" href="#6580" class="Datatype">⊤</a><a name="7295" class="Symbol">)</a><a name="7296">
</a><a name="7299" href="#7249" class="Function">k-exp-eq</a><a name="7307"> </a><a name="7308" href="#7308" class="Bound">A</a><a name="7309"> </a><a name="7310" class="Symbol">=</a><a name="7311"> </a><a name="7312" href="" class="Function">ap</a><a name="7314"> </a><a name="7315" class="Symbol">(λ</a><a name="7317"> </a><a name="7318" href="#7318" class="Bound">X</a><a name="7319"> </a><a name="7320" class="Symbol">→</a><a name="7321"> </a><a name="7322" href="#7308" class="Bound">A</a><a name="7323"> </a><a name="7324" class="Symbol">→</a><a name="7325"> </a><a name="7326" href="#7318" class="Bound">X</a><a name="7327" class="Symbol">)</a><a name="7328"> </a><a name="7329" href="#7209" class="Function">k-eq</a></code></pre>
<p>If we were working in a theory with computational univalence, coercion along <code>k-exp-eq</code> would reduce to precomposition with <span class="math">\(k\)</span>. In any case, we can manually show that this is the case propositionally by using path induction and the computational rule for <code>≈⇒≡</code>:</p>
<pre class="Agda"><code><a name="7609"></a><a name="7626" href="#7626" class="Function">ap-comp</a><a name="7633"> </a><a name="7634" class="Symbol">:</a><a name="7635"> </a><a name="7636" class="Symbol">∀</a><a name="7637"> </a><a name="7638" class="Symbol">{</a><a name="7639" href="#7639" class="Bound">i</a><a name="7640"> </a><a name="7641" href="#7641" class="Bound">k</a><a name="7642" class="Symbol">}{</a><a name="7644" href="#7644" class="Bound">A</a><a name="7645"> </a><a name="7646" class="Symbol">:</a><a name="7647"> </a><a name="7648" class="PrimitiveType">Set</a><a name="7651"> </a><a name="7652" href="#7639" class="Bound">i</a><a name="7653" class="Symbol">}{</a><a name="7655" href="#7655" class="Bound">X</a><a name="7656"> </a><a name="7657" href="#7657" class="Bound">X'</a><a name="7659"> </a><a name="7660" class="Symbol">:</a><a name="7661"> </a><a name="7662" class="PrimitiveType">Set</a><a name="7665"> </a><a name="7666" href="#7641" class="Bound">k</a><a name="7667" class="Symbol">}</a><a name="7668">
</a><a name="7679" class="Symbol">→</a><a name="7680"> </a><a name="7681" class="Symbol">(</a><a name="7682" href="#7682" class="Bound">p</a><a name="7683"> </a><a name="7684" class="Symbol">:</a><a name="7685"> </a><a name="7686" href="#7655" class="Bound">X</a><a name="7687"> </a><a name="7688" href="" class="Datatype Operator">≡</a><a name="7689"> </a><a name="7690" href="#7657" class="Bound">X'</a><a name="7692" class="Symbol">)</a><a name="7693">
</a><a name="7704" class="Symbol">→</a><a name="7705"> </a><a name="7706" class="Symbol">(</a><a name="7707" href="#7707" class="Bound">f</a><a name="7708"> </a><a name="7709" class="Symbol">:</a><a name="7710"> </a><a name="7711" href="#7644" class="Bound">A</a><a name="7712"> </a><a name="7713" class="Symbol">→</a><a name="7714"> </a><a name="7715" href="#7655" class="Bound">X</a><a name="7716" class="Symbol">)</a><a name="7717">
</a><a name="7728" class="Symbol">→</a><a name="7729"> </a><a name="7730" href="" class="Function">coerce</a><a name="7736"> </a><a name="7737" class="Symbol">(</a><a name="7738" href="" class="Function">ap</a><a name="7740"> </a><a name="7741" class="Symbol">(λ</a><a name="7743"> </a><a name="7744" href="#7744" class="Bound">X</a><a name="7745"> </a><a name="7746" class="Symbol">→</a><a name="7747"> </a><a name="7748" href="#7644" class="Bound">A</a><a name="7749"> </a><a name="7750" class="Symbol">→</a><a name="7751"> </a><a name="7752" href="#7744" class="Bound">X</a><a name="7753" class="Symbol">)</a><a name="7754"> </a><a name="7755" href="#7682" class="Bound">p</a><a name="7756" class="Symbol">)</a><a name="7757"> </a><a name="7758" href="#7707" class="Bound">f</a><a name="7759">
</a><a name="7770" href="" class="Datatype Operator">≡</a><a name="7771"> </a><a name="7772" href="" class="Function">coerce</a><a name="7778"> </a><a name="7779" href="#7682" class="Bound">p</a><a name="7780"> </a><a name="7781" href="" class="Function Operator">∘</a><a name="7782"> </a><a name="7783" href="#7707" class="Bound">f</a><a name="7784">
</a><a name="7787" href="#7626" class="Function">ap-comp</a><a name="7794"> </a><a name="7795" href="" class="InductiveConstructor">refl</a><a name="7799"> </a><a name="7800" href="#7800" class="Bound">f</a><a name="7801"> </a><a name="7802" class="Symbol">=</a><a name="7803"> </a><a name="7804" href="" class="InductiveConstructor">refl</a><a name="7808">
</a><a name="7812" href="#7812" class="Function">k-exp-eq-comp'</a><a name="7826"> </a><a name="7827" class="Symbol">:</a><a name="7828"> </a><a name="7829" class="Symbol">∀</a><a name="7830"> </a><a name="7831" class="Symbol">{</a><a name="7832" href="#7832" class="Bound">i</a><a name="7833" class="Symbol">}{</a><a name="7835" href="#7835" class="Bound">A</a><a name="7836"> </a><a name="7837" class="Symbol">:</a><a name="7838"> </a><a name="7839" class="PrimitiveType">Set</a><a name="7842"> </a><a name="7843" href="#7832" class="Bound">i</a><a name="7844" class="Symbol">}(</a><a name="7846" href="#7846" class="Bound">f</a><a name="7847"> </a><a name="7848" class="Symbol">:</a><a name="7849"> </a><a name="7850" href="#7835" class="Bound">A</a><a name="7851"> </a><a name="7852" class="Symbol">→</a><a name="7853"> </a><a name="7854" href="#6580" class="Datatype">⊤</a><a name="7855" class="Symbol">)</a><a name="7856">
</a><a name="7874" class="Symbol">→</a><a name="7875"> </a><a name="7876" href="" class="Function">coerce</a><a name="7882"> </a><a name="7883" class="Symbol">(</a><a name="7884" href="#7249" class="Function">k-exp-eq</a><a name="7892"> </a><a name="7893" href="#7835" class="Bound">A</a><a name="7894" class="Symbol">)</a><a name="7895"> </a><a name="7896" href="#7846" class="Bound">f</a><a name="7897">
</a><a name="7915" href="" class="Datatype Operator">≡</a><a name="7916"> </a><a name="7917" class="Symbol">λ</a><a name="7918"> </a><a name="7919" href="#7919" class="Bound">_</a><a name="7920"> </a><a name="7921" class="Symbol">→</a><a name="7922"> </a><a name="7923" href="#6600" class="InductiveConstructor">tt</a><a name="7925">
</a><a name="7928" href="#7812" class="Function">k-exp-eq-comp'</a><a name="7942"> </a><a name="7943" href="#7943" class="Bound">f</a><a name="7944"> </a><a name="7945" class="Symbol">=</a><a name="7946"> </a><a name="7947" href="#7626" class="Function">ap-comp</a><a name="7954"> </a><a name="7955" href="#7209" class="Function">k-eq</a><a name="7959"> </a><a name="7960" href="#7943" class="Bound">f</a><a name="7961">
</a><a name="7981" href="" class="Function Operator">·</a><a name="7982"> </a><a name="7983" href="" class="Function">ap</a><a name="7985"> </a><a name="7986" class="Symbol">(λ</a><a name="7988"> </a><a name="7989" href="#7989" class="Bound">c</a><a name="7990"> </a><a name="7991" class="Symbol">→</a><a name="7992"> </a><a name="7993" href="#7989" class="Bound">c</a><a name="7994"> </a><a name="7995" href="" class="Function Operator">∘</a><a name="7996"> </a><a name="7997" href="#7943" class="Bound">f</a><a name="7998" class="Symbol">)</a><a name="7999">
</a><a name="8024" class="Symbol">(</a><a name="8025" href="" class="Function">uni-coherence</a><a name="8038"> </a><a name="8039" class="Symbol">(</a><a name="8040" href="#6884" class="Function">k</a><a name="8041"> </a><a name="8042" href="" class="InductiveConstructor Operator">,</a><a name="8043"> </a><a name="8044" href="#6908" class="Function">k-we</a><a name="8048" class="Symbol">))</a></code></pre>
<p>Now it’s easy to conclude that <span class="math">\(A → ⊤\)</span> is a mere proposition (hence contractible): given functions <span class="math">\(f g : A → ⊤\)</span>, precomposing them with <span class="math">\(k\)</span> makes them both equal to <span class="math">\(λ \_ → \mathsf{tt}\)</span>. Since precomposing with <span class="math">\(k\)</span> is an equivalence by the computational rule above, <span class="math">\(f\)</span> must be equal to <span class="math">\(g\)</span>.</p>
<pre class="Agda"><code><a name="8356"></a><a name="8373" href="#8373" class="Function">prop-exp-⊤</a><a name="8383"> </a><a name="8384" class="Symbol">:</a><a name="8385"> </a><a name="8386" class="Symbol">∀</a><a name="8387"> </a><a name="8388" class="Symbol">{</a><a name="8389" href="#8389" class="Bound">i</a><a name="8390" class="Symbol">}{</a><a name="8392" href="#8392" class="Bound">A</a><a name="8393"> </a><a name="8394" class="Symbol">:</a><a name="8395"> </a><a name="8396" class="PrimitiveType">Set</a><a name="8399"> </a><a name="8400" href="#8389" class="Bound">i</a><a name="8401" class="Symbol">}</a><a name="8402"> </a><a name="8403" class="Symbol">→</a><a name="8404"> </a><a name="8405" href="" class="Function">prop</a><a name="8409"> </a><a name="8410" class="Symbol">(</a><a name="8411" href="#8392" class="Bound">A</a><a name="8412"> </a><a name="8413" class="Symbol">→</a><a name="8414"> </a><a name="8415" href="#6580" class="Datatype">⊤</a><a name="8416" class="Symbol">)</a><a name="8417">
</a><a name="8420" href="#8373" class="Function">prop-exp-⊤</a><a name="8430"> </a><a name="8431" class="Symbol">{</a><a name="8432" href="#8432" class="Bound">i</a><a name="8433" class="Symbol">}{</a><a name="8435" href="#8435" class="Bound">A</a><a name="8436" class="Symbol">}</a><a name="8437"> </a><a name="8438" href="#8438" class="Bound">f</a><a name="8439"> </a><a name="8440" href="#8440" class="Bound">g</a><a name="8441"> </a><a name="8442" class="Symbol">=</a><a name="8443"> </a><a name="8444" href="" class="Function">ap</a><a name="8446"> </a><a name="8447" href="" class="Function">proj₁</a><a name="8452">
</a><a name="8457" class="Symbol">(</a><a name="8458"> </a><a name="8459" href="" class="Function">contr⇒prop</a><a name="8469"> </a><a name="8470" class="Symbol">(</a><a name="8471" href="" class="Function">coerce-equiv</a><a name="8483"> </a><a name="8484" class="Symbol">(</a><a name="8485" href="#7249" class="Function">k-exp-eq</a><a name="8493"> </a><a name="8494" href="#8435" class="Bound">A</a><a name="8495" class="Symbol">)</a><a name="8496"> </a><a name="8497" class="Symbol">(λ</a><a name="8499"> </a><a name="8500" href="#8500" class="Bound">_</a><a name="8501"> </a><a name="8502" class="Symbol">→</a><a name="8503"> </a><a name="8504" href="#6600" class="InductiveConstructor">tt</a><a name="8506" class="Symbol">))</a><a name="8508">
</a><a name="8517" class="Symbol">(</a><a name="8518" href="#8438" class="Bound">f</a><a name="8519"> </a><a name="8520" href="" class="InductiveConstructor Operator">,</a><a name="8521"> </a><a name="8522" href="#7812" class="Function">k-exp-eq-comp'</a><a name="8536"> </a><a name="8537" href="#8438" class="Bound">f</a><a name="8538" class="Symbol">)</a><a name="8539">
</a><a name="8548" class="Symbol">(</a><a name="8549" href="#8440" class="Bound">g</a><a name="8550"> </a><a name="8551" href="" class="InductiveConstructor Operator">,</a><a name="8552"> </a><a name="8553" href="#7812" class="Function">k-exp-eq-comp'</a><a name="8567"> </a><a name="8568" href="#8440" class="Bound">g</a><a name="8569" class="Symbol">)</a><a name="8570"> </a><a name="8571" class="Symbol">)</a><a name="8572">
</a><a name="8576" href="#8576" class="Function">contr-exp-⊤</a><a name="8587"> </a><a name="8588" class="Symbol">:</a><a name="8589"> </a><a name="8590" class="Symbol">∀</a><a name="8591"> </a><a name="8592" class="Symbol">{</a><a name="8593" href="#8593" class="Bound">i</a><a name="8594" class="Symbol">}{</a><a name="8596" href="#8596" class="Bound">A</a><a name="8597"> </a><a name="8598" class="Symbol">:</a><a name="8599"> </a><a name="8600" class="PrimitiveType">Set</a><a name="8603"> </a><a name="8604" href="#8593" class="Bound">i</a><a name="8605" class="Symbol">}</a><a name="8606"> </a><a name="8607" class="Symbol">→</a><a name="8608"> </a><a name="8609" href="" class="Function">contr</a><a name="8614"> </a><a name="8615" class="Symbol">(</a><a name="8616" href="#8596" class="Bound">A</a><a name="8617"> </a><a name="8618" class="Symbol">→</a><a name="8619"> </a><a name="8620" href="#6580" class="Datatype">⊤</a><a name="8621" class="Symbol">)</a><a name="8622">
</a><a name="8625" href="#8576" class="Function">contr-exp-⊤</a><a name="8636"> </a><a name="8637" class="Symbol">=</a><a name="8638"> </a><a name="8639" class="Symbol">(λ</a><a name="8641"> </a><a name="8642" href="#8642" class="Bound">_</a><a name="8643"> </a><a name="8644" class="Symbol">→</a><a name="8645"> </a><a name="8646" href="#6600" class="InductiveConstructor">tt</a><a name="8648" class="Symbol">)</a><a name="8649"> </a><a name="8650" href="" class="InductiveConstructor Operator">,</a><a name="8651"> </a><a name="8652" href="#8373" class="Function">prop-exp-⊤</a><a name="8662"> </a><a name="8663" class="Symbol">_</a></code></pre>