<<

Theory for Functional Programmers , Natural Transformations, Adjunctions

Nick Hu University of Oxford [email protected] ABSTRACT GROUNDWORK

Category Theory is a very abstract theory of mathematical A category 풞 is defined by a collection of objects, ob (풞), and structure, which has strong links with functional program- a collection of , hom (풞), which are maps between ming. In this essay, I explore basic construc- objects. A 푓 has a domain dom (푓) and a codomain tions using insights from functional programming to provide cod (푓), which are objects, and 푓∶ 푋 → 푌 or equivalently 푓 examples and motivation. The categorical triad of functori- 푋 → 푌 is written to denote that 푓 is a morphism with ality, naturality, and universality (adjunction) is ubiquitous domain 푋 and codomain 푌. in mathematical spheres, and I aim to cover it in a brief yet elucidating manner, unburdened from complex heavy rigour Categories must also satisfy the following conditions: present in almost any graduate text on category theory. • for each object 푋, there exists a morphism idX ∶ 푋 → 푋; • for any two morphisms 푓∶ 푋 → 푌, 푔∶ 푌 → 푍, there exists a composite morphism 푔 ∘ 푓∶ 푋 → 푍. INTRODUCTION Composition must be associative, and identity morphisms must act as a unit to composition, as shown in the following Categories are the essence of composition, category theory commutative diagrams: yields a ubiquitous language interesting to logicians, philoso- 푓 푓 phers, computer scientists, mathematicians, and physicists 푋 푌 푋 푌 alike. In fact, Baez (2010) goes on to suggest that often idX idY different concepts in wildly different disciplines are actually 푓 푓 merely different exposition for ‘the same’ phenomena. 푋 푌

For computer science especially, category theory ‘gives a In a category, identity morphisms are necessarily unique. precise handle on important notions such as compositional- The category which we are primarily interested in is Hask, ity, abstraction, representation-independence, genericity and which has Haskell types as its objects and Haskell functions more’ (Abramsky and Tzevelekos 2010). as its morphisms. More fundamental still, is that category theory attempts to To see that this forms a category, recall the polymorphic address and challenge the age-old problem of what formal : ‘equality’ means and what is actually desirable — notions of equality from theory are fraying at the edges in modern id :: a -> a mathematics, as seen in the new and fast-moving field of id x = x Homotopy Type Theory. then if any type A is an object of Hask, its identity mor- Certain categories, which will be touched on later, suffice to phism is given by the monomorphic specialisation of id to model computation and logic; a prime example of this is the id :: A -> A. relationship between the simply-typed 휆-calculus, intuitionis- Morphisms compose via ordinary Haskell function composi- tic logic, and Cartesian Closed Categories, as stipulated by tion (post monomorphic specialisation): the Curry-Howard-Lambek correspondence. (.) :: (b -> c) -> (a -> b) -> a -> c Much of this essay is inspired by Bartosz Milewski’s excellent (.) g f = \x -> g (f x) book on Category Theory for Programmers (2017), and that is where the title comes from — a lot of this work can be For Hask to really be a category, ‘fast and loose reasoning’ regarded as my personal distillation and insights from reading will be used to conveniently pretend that Haskell functions it, presented as briefly as I could justify. are total, and ignore concerns arising from ⊥ (Danielsson et al. 2006). Throughout this essay, I will make assertions in bold — the reader may treat these assertions as exercises to justify. These functions are sufficient to establish Hask as a category. Nick Hu

In category theory, we generally don’t care about what the is as translations between different representations of the objects are, but instead how they interact with each other same data — a linked list can be traversed and the contents (via morphisms). dumped into an array, and similarly a linked list can be built from the contents of an array. Other examples of a category include: • Set, with objects as sets and morphisms as set-functions between them; LIMITS AND COLIMITS • Pos, with objects as partially ordered sets and morphisms In a category 풞, a terminal object 1 is an object where every as monotone maps; other object 푋 in 풞 has a unique morphism 휄푋 targeting it • the category of a specific preordered set (푋, ≺), with 휄푋 objects 푥 ∈ 푋 and morphisms 푥 → 푦 ⟺ 푥 ≺ 푦;1 (i.e. ∀푋 ∈ ob (풞) ⋅ ∃! 휄푋 ⋅ 푋 → 1). Dually, an initial object 0 • the category of a specific monoid (푀, ⋅, 푒), with a single is an object where every other object 푋 in 풞 has a unique object and morphisms 푚 ∈ 푀. The identity morphism is morphism !푋 originating from it. Initial and terminal objects given by 푒, and composition is given by ⋅. If instead we are unique up to unique . have a , then all of the morphisms are ; In Set, ∅ is initial, and the singleton set {∗} is terminal. • Cat, with objects as categories2 and morphisms as func- To see why, consider the number of functions 푓푋 ∶ ∅ → 푋; tors; there is only one such function: the empty function. For any • 풞op, the dual category to 풞 with the direction of its set 푋, there is only one function 푓푋 ∶ 푋 → {∗}: the constant morphisms reversed — 푓∶ 푋 → 푌 ∈ hom (풞) ⟺ 푓∶ 푌 → op op function. This can be checked by considering that the number 푋 ∈ hom (풞 ). If 풞 = 풞 then 풞 is self-dual; |푋| of functions from two sets 푋 and 푌 is |푌| — for the initial • Rel, with objects as sets and relations as morphisms; 0 Rel is self-dual because relations are symmetric whereas object we have |푋| = 1, and for the terminal object we have |푋| functions are not. 1 = 1. The category Set is very important, and new concepts will In Hask, the initial object is a type Void which has no con- frequently be introduced via Set. structors. The unique morphism associated to it is: absurd :: Void -> a Isomorphism As Void has no inhabitants, there is no meaningful definition In a category 풞, if there is a morphism 푓∶ 푋 → 푌, and for this function, just as the empty set-function has no mean- a morphism 푔∶ 푌 → 푋 such that the following diagram ingful . The unit type, (), is terminal, and the unique commutes: morphism associated to it is: 푓 unit :: a -> () id 푋 푌 id X 푔 Y unit _ = () then 푋 and 푌 are isomorphic, and 푓 and 푔 are isomorphisms. or equivalently unit = const (). The problem of equality is a far-ranging one, but the usual def- A useful, but naïve, intuition for the relationship between inition of extensional equality (or even intensional equality) is Hask and Set is to treat each type as a set with cardinality often too strict. In category theory, isomorphism is commonly equal to the number of inhabitants of that type. Void has no regarded as a sufficient notion of ‘sameness’; often, category inhabitants, and thus corresponds to the empty set. Similarly, theorists come up with universal constructions establishing unit has a single inhabitant () — it is unimportant what some property that is ‘unique up to unique isomorphism’ that is, because all singleton sets are trivially canonically (canonical isomorphism). isomorphic. An analogy from programming is the abstraction barrier: in A product of two sets 푋 and 푌 is traditionally given general, we don’t really care how an interface is implemented by {(푥, 푦) ∣ 푥 ∈ 푋, 푦 ∈ 푌} — the con- given that it fully satisfies the specification. A stack can be struction. The product can alternatively be defined to be implemented using a linked list, a heap, or an array, and {(푦, 푥)|푥 ∈ 푋, 푦 ∈ 푌}, or even {(푥, ∅, 푦) ∣ 푥 ∈ 푋, 푦 ∈ 푌}. As correct implementations will behave indistinguishably in the long as our theorems about products of sets are aware of abstract — in the concrete, implementations will behave which representation is chosen, they still hold, and indeed differently, but beyond the concern of rationally reasoning these representations are isomorphic to each other. about correctness. Another way of viewing the isomorphisms Categorically, this implementation detail can be abstracted 1Identity morphisms exist due to the reflexivity of the ordering relation, away, and instead a product is defined in terms of an abstract and composite morphisms from transitivity. 푋 푌 2 interface: a product of two objects and is an object Which are small — 풞 is small when its collections of objects and 푋 × 푌 휋 ∶ 푋 × 푌 → 푋 morphisms are set-sized. Cat itself is large, but otherwise we will only along with projection maps 1 and consider small categories. 휋2 ∶ 푋 × 푌 → 푌. Category Theory for Functional Programmers

푖 푖 However, this definition is insufficient — the Cartesian 푋 1 푋 + 푌 2 푌 set product 푋 × 푌 × {0, 1} as a categorical product of objects 푋 and 푌 in Set, with projection maps 휋 (푥, 푦, 0) ↦ 푥, [푓,푔] 1 푓 푔 휋1(푥, 푦, 1) ↦ 푥 (and similarly for 휋2) satisfies this definition, but this ‘product’ contains an extra bit of information. We 푍 want our notions of product to be isomorphic to each other, In Set, the of 푋 and 푌 is given by the disjoint but there is no canonical mapping between the Cartesian set union 푋 ⊎ 푌. In Hask, of types are sum types products 푋 × 푌 → 푋 × 푌 × {0, 1}. But the reverse map exists tagged by constructors; the canonical example: canonically by simply forgetting the extra bit of information; in general, this corresponds to the existence of a morphism data Either a b = Left a | Right b in Set from ‘products’ with too much information, to the is the coproduct of polymorphic types a and b, with con- traditional Cartesian product. structors Left :: a -> Sum a b and Right :: b -> Sum a Hence, for a satisfying definition of product, we require the b providing the injection maps. product object 푋 × 푌 be the ‘most extreme’ object in some The existence of binary (co) products and a (initial) terminal sense (hence ); given a third object 푍 and morphisms object implies the existence of arbitrary finite (co) products. 푓∶ 푍 → 푋 and 푔∶ 푍 → 푌, we require there to exist a unique morphism ⟨푓, 푔⟩∶ 푍 → 푋 × 푌 making the following diagram commute:3 Algebra of types

푍 These types are called ‘algebraic data types’ because Hask 푓 푔 is a with respect to product, in the sense ⟨푓,푔⟩ that a is isomorphic to (a, ()) (the product of a and the 푋 푋 × 푌 푌 terminal object ()). As witness to the isomorphism: 휋1 휋2 rho :: (a, ()) -> a 푍 corresponds to our object with necessary projection maps; a rho = fst ‘product’ which might have too much information — if it truly is a product, then by definition there would exist a unique rho_inv :: a -> (a, ()) morphism 푋 × 푌 → 푍 establishing a unique isomorphism rho_inv x = (x, ()) between 푍 and 푋 × 푌. Another way of thinking about this is that 푓 and 푔 factor through ⟨푓, 푔⟩. Hask is also monoidal with respect to coproduct (sum), with a being isomorphic to Either a Void (the coproduct of a In doing this, a more universal notion of product independent and the initial object Void). As Void is uninhabited, only from set membership ∈ is given, and it doesn’t matter which terms with the Left constructor can be created, and so the one is used as products are canonically isomorphic (unique isomorphism is just to deconstruct or it. up to unique isomorphism). Using the categorical syntax, we have established: Cartesian set products are an instance of categorical product if 푎 is an object in Hask, then, in Set, with the obvious projection maps. In Hask, the product of types A and B is the tuple type (A, B) with projection • 푎 × 1 ≃ 푎 — monoidal with respect to product, terminal maps fst :: (a, b) -> a and snd :: (a, b) -> b. object as identity; • 푎 + 0 ≃ 푎 — monoidal with respect to coproduct, initial Some other examples of products: object as identity; • 푎 × 0 ≃ 0 — (a, Void) also has no inhabitants. • in the category of a specific partially ordered set, the product of two objects is its meet/infimum/greatest lower Stretching this analogy, it can be shown that products bound; distribute over sums: 푎 × (푏 + 푐) ≃ 푎 × 푏 + 푎 × 푐, or in • in the category of logic predicates, the product of two Haskell by showing that (a, Either b c) is isomorphic to objects is its logical conjunction. Either (a, b) (a, c). Such an isomorphism is witnessed by the following: Dually, there is a notion of coproduct: a coproduct of two distribute :: (a, Either b c) -> Either (a, b) (a, c) objects 푋 and 푌 is an object 푋 + 푌 along with injection maps distribute (x, Left y) = Left (x, y) 푖 ∶ 푋 → 푋 + 푌 and 푖 ∶ 푌 → 푋 + 푌 such that the following 1 2 distribute (x, Right z) = Right (x, z) diagram commutes: undistribute :: Either (a, b) (a, c) -> (a, Either b c) undistribute (Left (x, y)) = (x, Left y) 3A dashed arrow to is used to indicate uniqueness. undistribute (Right (x, z)) = (x, Right z) Nick Hu

This means that Hask has a semiring structure, and • 푋0 ≃ 1, the naturals are further interpreted as the num- • 1푋 ≃ 1, ber of inhabitants of a type. For instance, the type • 푋1 ≃ 푋, data Bool = True | False can be regarded as syntax • 푋푌 +푍 ≃ 푋푌 × 푋푍, sugar for data Bool = Either (True (), False ()) • (푋푌)푍 ≃ 푋푌 ×푍, where True and False are tags distinguishing distinct • (푋 × 푌 )푍 ≃ 푋푍 × 푌 푍. singleton types; rewriting this categorically, we get Bool = 1 + 1 = 2. These identities can be interpreted in Hask by polymorphic invertible functions which serve as witness to the isomor- A more interesting example is the cons list: phism, in the same fashion as the previous section on algebraic data types. data List a = Nil | Cons a (List a) -- desugaring Nil and Cons into tags, uncurrying Cons data List a = Either (Nil (), Cons (a, (List a))) Curry-Howard-Lambek 푥 Categorically, writing for List a: If a category has a terminal object, binary products, and 푥 = 1 + 푎 × 푥 exponential objects, then it is Cartesian Closed. A Cartesian (CCC) provides sufficient structure to model = 1 + 푎 × (1 + 푎 × 푥) = 1 + 푎 + 푎2 × 푥 the simply-typed 휆-calculus, which is the core of functional = 1 + 푎 × (1 + 푎 × (1 + 푎 × 푥)) = 1 + 푎 + 푎2 + 푎3 × 푥 programming. It also models intuitionistic logic; consult the = … following translation table (using Hask as an approximation for simply-typed 휆-calculus): which precisely describes a list: it is a singleton (empty list), or an a in a singleton list, or a 2-tuple (a, a) corresponding Table 1: Curry-Howard-Lambek correspondence to the 2-length list, etc. CCC 풞 Intuitionistic Logic Hask EXPONENTIALS 0 ⊥ Void 1 ⊤ () In Set, the collection of morphisms from two sets 푋 and 푋 × 푌 푥 ∧ 푦 (a, b) 푌 itself forms a set, which is called a hom-set, denoted by 푋 + 푌 푥 ∨ 푦 Either a b Set(푋, 푌 ) or 푌 푋. As the objects of Set are all sets, 푌 푋 is 푌 푋 푥 → 푦 a -> b also an object of Set, so it is described as internal. Hask also has internal hom-sets in the form of function types. Now, our evaluation morphism 휖∶ 푌 푋 × 푋 → 푌 is interpreted To describe this abstractly in the language of category theory, in Hask as a function :: ((a -> b), a) -> a which this notion needs to be related to objects and morphisms. Let corresponds to function application, and in logic as ((푥 → 푋, 푌, and 푌 푋 be objects in a category 풞 with binary products 푦) ∧ 푥) → 푦 — modus ponens. The Curry-Howard part of such that there exists an evaluation morphism 휖∶ 푌 푋×푋 → 푌. the correspondence goes to say that a proof of a theorem is 푌 푋 is an if for any other 푍 and 푓∶ 푍×푋 → equivalent to a typed expression with a type corresponding 푌, there is a unique morphism 푓 ∶̃ 푍 → 푌 푋 that factors 푓 to the formula. To prove such a theorem, it suffices to show 휖 푓 = 휖 ∘ (푓̃ × id ) 4 through : X . that eval’s type is inhabited: Equivalently, the following diagram commutes: eval :: ((a -> b), a) -> b 푌 푋 × 푋 휖 푌 eval (f, x) = f x ̃ and therefore modus ponens is a valid theorem in intuitionis- 푓×idX 푓 tic logic. 푍 × 푋 In the same vein, the absurd function is an interpretation of ̃ Looking at 푓, we see that it takes an object and gives us an ex falso quodlibet (⊥ → 푥). exponential object, corresponding to a in Hask; this allows us to interpret 푓 ̃as the curried version of 푓, and In fact, the Curry-Howard-Lambek correspondence states 휆 our factorisation recovering 푓 from 푓 ̃gives uncurrying. that simply-typed -calculus, intuitionistic logic, and CCCs are isomorphic. The notation for the exponential objects is no coincidence, and the normal algebraic identities just fall out (with equality swapped for isomorphism): FUNCTORIALITY

4The product of morphisms will be justified later, in the discussion of A is a structure-preserving map between categories, ̃ ̃ the product functor, but for now 푓 × idX = ⟨푓, idX⟩. which preserves composition and identity morphisms; given Category Theory for Functional Programmers categories 풞 and 풟, and a functor 퐹∶ 풞 → 풟 between them, object 푋 in 풞 to the hom-set 풞(퐴, 푋), and each morphism we have: 푓∶ 푋 → 푌 to 풞(퐴, 푓)∶ 풞(퐴, 푋) → 풞(퐴, 푌 ) with mapping 푔 ↦ 푓 ∘ 푔 for each function 푔 in the hom-set 풞(퐴, 푋). • 퐹 (푓∶ 푋 → 푌 ) = 퐹 (푓)∶ 퐹 (푋) → 퐹 (푌 ); • for every object 푋 in 풞, 퐹 (idX) = idF(X) in 풟; In Hask, this is known as the Reader functor: • 퐹 (푔 ∘ 푓) = 퐹 (푔) ∘ 퐹 (푓) whenever 푔 ∘ 푓 is defined in 풞.5 풞 풟 type Reader a b = a -> b Some examples of functors: instance Functor (Reader a) where fmap = (.) • the forgetful functor from Mon to Set, which maps each monoid to its underlying set (monoid homomorphisms Similarly, the contravariant hom-functor 풞 (−, 퐵) ∶ 풞 → Set are weakened to functions); is also defined, but the morphism map is instead postcompo- • the selection functor mapping the trivial singleton cate- sition: gory to any non-empty category 풞; type Coreader a b = b -> a • the constant functor Δ ∶ 풞 → 풟 mapping every object 푋 instance Contravariant (Coreader a) where of 풞 to 푋 in 풟, and every morphism of 풞 to id , X contramap = flip (.) • the diagonal functor Δ∶ 풞 → 풞 × 풞 mapping objects 푋 in 풞 to 푋 × 푋 in the of 풞 with itself, Functors which are naturally isomorphic to a hom-functor 풞 × 풞, are called representable. • the product functor − × −∶ 풞 × 풞 → 풞, assuming 풞 has binary products, mapping every object (푋, 푌 ) in 풞 × 풞 to In Hask, this can be encoded as follows: ′ ′ 푋×푌 in 풞, and every morphism (푓, 푔)∶ (푋, 푌 ) → (푋 , 푌 ) Representable f where ′ ′ to 푓 ×푔∶ 푋 ×푌 → 푋 ×푌 . 푓 ×푔 is given by ⟨푓 ∘휋1, 푔 ∘휋2⟩. type Rep f :: Type In Hask, functors6 are given by the Functor typeclass: tabulate :: (Rep f -> x) -> f x index :: f x -> (Rep f -> x) class Functor f where 7 fmap :: (a -> b) -> (f a -> f b) We can think of the as a statically- sized data structure which can be encoded as data in memory The type constructor gives the object mapping, and fmap f x, or isomorphically as a function from the indexing type gives the morphism mapping. to the data type Rep f -> x, along with methods to trans- One intuition for Haskell functors is containers; for example form between the two encodings; i.e. the following diagram the Haskell list [] is a functor with fmap given by the standard commutes: map function on lists. The option type Maybe is also functorial: index f x Rep f -> x tabulate instance Functor Maybe where fmap f Nothing = Nothing A good example of this is a statically-sized vector of size 푛 fmap f (Just x) = Just (f x) — the Rep type is the finitely bounded naturals [0, 푛), which give the indices of the vector. Then the Rep f -> x encoding and so is Either a. is interpreted as a sparse vector, and f x as a dense one. The representable functor formalises the idea that these two Contravariance encodings are ‘the same data’ (isomorphism), and gives a method to convert between the two, but in a computational The functors presented so far are covariant functors. A functor context one may be preferable over the other. 퐹∶ 풞 → 풟 is contravariant if it maps morphisms 푓∶ 푋 → 푌 in 풞 to 퐹 (푓)∶ 퐹 (푌 ) → 퐹 (푋) in D. This is the same as a The pair type (a, b) is Representable in the same fashion. covariant functor from 풞op to 풟. In Hask, this corresponds to a different typeclass: NATURALITY class Contravariant f where contramap :: (b -> a) -> (f a -> f b) It is only natural to wonder if there is a notion of mapping between functors; let 퐹 and 퐺 be two functors from 풞 to 풟, then a 훼 from 퐹 and 퐺, denoted Hom-functors 훼∶ 퐹 ⇒ 퐺 is a family of morphisms 훼푋 ∶ 퐹 (푋) → 퐺(푋) indexed by objects 푋 in 풞. Each particular morphism is 퐴 퐵 풞 For objects and in a category , the covariant hom- called the component of 훼 at 푋. The functors of the natural 풞 (퐴, −) ∶ 풞 → 풞 (퐴, −) functor Set is defined. maps each transformation must map morphisms identically, and the 5 natural transformation must make the following diagram Sometimes ∘풞 will be used to denote the composition in category 풞 where ambiguity may arise. 6More specifically, endofunctors — functors from a category back into 7Also called a Naperian functor, where Rep f is like a logarithm of f itself; in this case, Hask. (Gibbons 2017). Nick Hu

퐹(푓) (naturality square) commute for each morphism 푓∶ 푋 → 푌 in 퐹 (푋) 퐹 (푌 ) 풞:

훼푋 훼푌 퐹(푓) 퐹 (푋) 퐹 (푌 ) 퐺(푓) 퐺(푋) 퐺(푌 ) 훼푋 훼푌 훽푋 훽푌 퐺(푋) 퐺(푌 ) 퐻(푓) 퐺(푓) 퐻(푋) 퐻(푌 )

If every component of a natural transformation is an isomor- Cat is actually Cartesian closed, with the phism, then it is a natural isomorphism, and this is our best [풞, 풟] as the exponential object 풟풞. notion for two functors being ‘the same’.

Thinking about the components, natural transformation can ADJUNCTION be considered as a mapping of objects to morphisms, such that the resultant morphism has a commuting naturality Two categories 풞 and 풟 are equivalent if there are a pair of square. A lot of commuting diagrams that are required in functors 퐿∶ 풞 → 풟 and 푅∶ 풟 → 풞 such that the composition order to fulfil a particular property is really a naturality in either direction is naturally isomorphic to the identity square in disguise, given the correct choice of functors. functor of the respective category. Adjunction is a slightly weaker notion than this, and it ap- In , a natural transformation looks like: Hask pears everywhere in mathematics and computer science. More specifically, it is weaker in the sense that the composite func- alpha :: (Functor f, Functor g) => F a -> G a tor need not be naturally isomorphic to the identity functor, The genericity provided by the parametric polymorphic type but these directions of natural transformations should exist: a suffices to define the whole natural transformation, and 휂∶ 퐼풞 ⇒ 푅 ∘ 퐿, this is a good intuition to understand them. In fact, due to 휖∶ 퐿 ∘ 푅 ⇒ 퐼 . parametricity, in Hask the naturality condition: 풟

(fmap f :: G a -> G b) . (alpha :: F a -> G a) = (alpha :: F b -> G b) . (fmap f :: F a -> F b) 휂 and 휖 are called the unit and counit of the adjunction respectively, and we use the notation 퐿 ⊣ 푅 to denote that 퐿 arises automatically for a function f :: a -> b, as a result is the left-adjoint functor to 푅, and that 푅 is the right-adjoint of free theorems (Wadler 1989). Furthermore, all the types functor to 퐿. can be inferred. Adjunctions are subject to the following triangle identities If a functor is a generalisation of a container, then a natural (in the functor category): transformation is the generalisation of repacking data from 퐿∘휂 휂∘푅 different containers. Naturality is the independence between 퐿 퐿 ∘ 푅 ∘ 퐿 푅 ∘ 퐿 ∘ 푅 푅 transforming the data with fmap and repacking — these two 휖∘퐿 푅∘휖 operations commute. 퐿 푅 Another interesting property is that because all standard algebraic data types are functorial, polymorphic functions where the double line is the identity natural transformation. between them are actually natural transformations (in the In Hask, the unit is called: to Hask, as function types are contravari- ant). return :: a -> m a and the counit is: Functor categories extract :: m a -> a

A functor category of 풞 and 풟, denoted by [풞, 풟], is a cate- which are exactly the lifting/unlifting operations of the Monad gory in which the objects are functors 풞 → 풟, and morphisms and Comonad typeclasses — fundamentally, every monad and are natural transformations between them. Compositions of comonad arises from adjunction. morphisms are given by the vertical composition of natu- An alternative but equivalent definition of adjunction can be ral transformations, as shown in the following commuting given in terms of hom-functors; given 푋, an object of 풞, and diagram, given another functor 퐻∶ 풞 → 풟 and natural trans- 푌, an object of 풟, an adjunction consists of functors 퐿 and formation 훽∶ 퐺 ⇒ 퐻: 푅 along with a natural isomorphism Category Theory for Functional Programmers

휓푋,푌 • Right preserve limits, and left adjoint 풞(푋, 푅(푌 )) 풟(퐿(푋), 푌 ) functors preserve colimits. 휙푋,푌 • Monads, Kleisli categories, and Eilenberg-Moore algebras. From this definition, unit can be derived: REFERENCES

∀푌 ∈ ob (풟) ⋅ 풟(퐿(푋), 푌 ) ≃ 풞(푋, 푅(푌 )) Abramsky, Samson, and Nikos Tzevelekos. 2010. “Introduc- ⟹ 풟(퐿(푋), 퐿(푋)) ≃ 풞(푋, (푅 ∘ 퐿)(푋)) tion to Categories and .” In New Structures for Physics, 3–94. Springer. = 풞(퐼푋(푋), (푅 ∘ 퐿)(푋)) Baez, John, and Mike Stay. 2010. “Physics, Topology, Logic which precisely gives the natural transformation 휂 at each and Computation: A Rosetta Stone.” In New Structures for component 푋 by taking idX along 휙푋,푌. Physics, 95–172. Springer. The counit can be derived similarly, and the hom-functor def- Danielsson, Nils Anders, John Hughes, Patrik Jansson, and inition can be derived from unit and counit. Jeremy Gibbons. 2006. “Fast and Loose Reasoning Is Morally Correct.” SIGPLAN Not. 41 (1). New York, NY, USA: ACM: Many universal constructions, including product and expo- 206–17. doi:10.1145/1111320.1111056. nential, arise from adjunction. Gibbons, Jeremy. 2017. “APLicative Programming with A free construction, given functorially, is a nice notion of Naperian Functors.” In European Symposium on Program- ‘canonical’ ways to create structure; for instance, given any ming, edited by Hongseok Yang, 10201:568–83. LNCS. set 푋, a free monoid consisting of elements of that set un- doi:10.1007/978-3-662-54434-1_21. der concatenation can be generated, introducing a special Milewski, Bartosz. 2017. “Category Theory for Pro- null-character 휖 as an identity (very similar to Kleene star grammers.” https://bartoszmilewski.com/2014/10/28/ construction). Free functors are left adjoint to a forgetful category-theory-for-programmers-the-preface/. functor, which ‘forgets’ some structure. The free monoid func- tor from Set to Mon is left adjoint to the forgetful functor Wadler, Philip. 1989. “Theorems for Free!” In Proceedings of from Mon to Set which maps each monoid to its underlying the Fourth International Conference on Functional Program- set. ming Languages and Computer Architecture, 347–59. FPCA ’89. New York, NY, USA: ACM. doi:10.1145/99370.99404. Following this, one intuition for adjunctions is as a way to create some sort of ‘canonical approximation’. Some more examples of free/forgetful adjunctions: • the category of ℤ with morphisms given by the ordering ≤ has a injection functor 푖∶ ℤ → ℝ – the floor and ceiling functors back into ℤ are right and left adjoints to 푖; • the category Top, of topological spaces and continuous maps, has a forgetful functor into Set which takes each topological space to its underlying set — the left adjoint takes a set to its ‘finest’ topology: the discrete topology whereby every element is a singleton open set; the right adjoint takes a set to its ‘coarsest’ topology, the trivial topology whereby only the whole set is open.

FURTHER TOPICS

• Cat as a 2-category, and . • More limit constructions: equalisers, pullbacks. • Limits and colimits in terms of universal cone/cocones. • Properties of functors: full, faithful, injective on objects and essentially surjective. Notions of embedding and equivalence described only with functors. • — all Set-valued functors arise via natural transformation of hom-functors. • Universal constructions via adjunction.