โ† back to index

Representable Functors

Bartosz Milewski ยท 2015 ยท Category Theory for Programmers, Ch. 13

Prereqs: ๐Ÿž Ch7 (Functors), ๐Ÿž Ch9 (Function Types). 8 min.

A functor F is representable if F(a) is isomorphic to Hom(r, a) for some object r. That means every container of type F is secretly a function from r. tabulate turns a function into the container; index turns the container back into a function. Round-trip: tabulate (index s) = s. This is memoization, stated categorically.

F(a) container index tabulate Hom(r, a) function natural isomorphism ≅

The hom-functor: functions as a functor

Fix a type r. The set of all functions r -> a depends on a functorially: given f : a -> b, you get (r -> a) -> (r -> b) by post-composing. This is the reader functor, also called the hom-functor Hom(r, -). A representable functor is one that's naturally isomorphic to this reader for some choice of r.

Scheme

Stream: an infinite container represented by Integer

An infinite stream holds one value for every natural number. That means a stream of a is the same information as a function Integer -> a. The representing object is Integer. tabulate builds a stream by calling the function at 0, 1, 2, ...; index walks the stream to the n-th element.

Scheme

The round-trip: tabulate and index are inverses

A functor is representable when tabulate and index are inverses. That means two laws hold: tabulate (index s) = s (build a stream from its own indexing function and you get the same stream) and index (tabulate f) = f (index into a tabulated function and you get back the original function). This is the natural isomorphism between F and Hom(r, -).

Scheme

Memoization: the computational meaning

Representability is memoization. A function r -> a computes a value on every call. tabulate converts it into a data structure that stores all the results. index retrieves them. The function and the data structure carry the same information, but the data structure trades space for time. Milewski: "a representable functor is a memoized function."

Scheme

Not every functor is representable

The list functor is not representable. A function r -> a always produces a value for every input, but a list can be empty. There's no representing object r such that [a] is isomorphic to r -> a for all a. Representable functors must have a fixed "shape" determined by the representing object. Lists have variable length, so they fail.

Scheme

fmap for free

If a functor is representable, you get fmap for free. To map f over a container: index it into a function, post-compose f, then tabulate the result. This is the reader functor's fmap transported through the isomorphism.

Scheme

Notation reference

Blog / Haskell Scheme Meaning
C(a, -)(lambda (x) (a -> x))Hom-functor / reader functor
Rep fInteger (for Stream)Representing object
tabulate :: (Rep f -> a) -> f a(tabulate f)Function to container
index :: f a -> Rep f -> a(stream-index s n)Container to function
tabulate . index = id(tabulate (lambda (n) (stream-index s n)))Round-trip law (container)
index . tabulate = id(stream-index (tabulate f) n) = (f n)Round-trip law (function)
Neighbors

Milewski chapters

Foundations (Wikipedia)

Translation notes

The blog post uses Haskell's Representable typeclass with an associated type Rep f. This page uses plain Scheme functions, since Scheme has no type system to enforce the isomorphism laws. Streams are implemented with thunks for lazy tails, approximating Haskell's lazy evaluation. The memoization example doesn't truly cache in Scheme (no lazy thunks), but the structure is identical: tabulate builds the lookup structure, index retrieves from it. The blog post also discusses the logarithmic interpretation (if F(a) = a^r then r = log F) and the connection to the Yoneda lemma (every natural transformation from a hom-functor to F corresponds to an element of F(r), but representability requires this correspondence to be an isomorphism, not just a mapping).

Ready for the real thing? Read the blog post. Start with the hom-functor review, then trace the Stream instance through tabulate and index.