Mappings That Preserve Structure
A category as objects, arrows and a composition satisfying two laws; a functor as a mapping that preserves those laws rather than merely matching up objects; the composite that detects a mapping which looks structural and is not; and naturality as a square that has to commute at every arrow.
Definition
A category consists of objects, arrows each with a source and target object, a composition assigning to arrows
A functor
The second law is what makes the mapping structural. A map can send every object somewhere sensible and give every arrow the right endpoints while failing it.
A natural transformation
This is the naturality square, and it is a condition at every arrow, not a property of the diagram being drawable.
In programming. Types and functions form a category. A type constructor with a map operation is a functor when map id = id and map (g . f) = map g . map f; a polymorphic function whose behaviour does not inspect the contained type is a natural transformation, and its naturality square is the statement that mapping before or after the function gives the same result.
Assumptions and scope
Composition must be defined exactly when the target of one arrow is the source of the next. A 'category' whose composition table pairs arrows that do not meet is not a category, and the error is in the data rather than in the laws.
Associativity and the identity laws are checked over every composable triple and every arrow. Verifying a sample establishes nothing, since a single failing triple refutes the structure.
A functor preserves sources and targets by definition, so a mapping violating that is not a candidate functor at all. The interesting failures are mappings that satisfy the endpoint conditions and break the composition law.
Naturality is a family of equations indexed by arrows, not by objects. A transformation can satisfy the square at several arrows and fail at another, so the check is not complete until every arrow has been examined.
A degenerate example can satisfy the laws for uninteresting reasons. When both functors are constant, every naturality square reduces to the same equation, which verifies the mechanics of the check without testing whether the two paths could differ.
In a programming setting the laws are claims about a concrete implementation, and a
mapthat reorders or duplicates elements can break them while type-checking. The compiler enforces the types and not the laws.
Worked material
Example
Five structures and whether the laws hold
A partial order as a category. Objects are the elements; there is one arrow
Lists with map. Objects are types, arrows are functions, and the list constructor with map is a functor when map id = id and map (g . f) = map g . map f. Both hold for the standard implementation. A variant that reverses the list while mapping type-checks identically and breaks the first law, since mapping the identity would reverse.
A monoid as a one-object category. One object, one arrow per element, composition is the monoid operation. Associativity of the category is associativity of the monoid; the identity arrow is the unit. A functor between two such categories is exactly a monoid homomorphism. The categorical laws reduce to the algebraic ones with nothing left over.
A mapping that collapses everything. Send every object of
reverse on lists as a natural transformation. For each type reverse maps a list of map f . reverse = reverse . map f, which holds because reversing rearranges positions without examining elements. Contrast sort, which inspects elements: map f . sort and sort . map f differ as soon as f does not preserve the ordering, so sort is not natural.
---
The first three are cases where familiar structures turn out to be categories and familiar maps turn out to be functors, so the laws recover what was already known. The fourth shows the laws are a floor, not a distinction. The fifth is the one that bites: two functions of the same type, one natural and one not, distinguished by an equation rather than by their signatures.
Contrast
Pairs that differ in one respect
| object map sensible | yes | yes |
| endpoints correct | yes | yes |
| yes | yes | |
| image of | ||
| composite of images | ||
| a functor | yes | no |
The first four rows are identical. Only the fifth comparison separates them, and it is the only row that could not be settled by inspection.
The typing condition against the composition law.
A mapping sending
Collapsing against contradicting.
reverse against sort.
Both have the same shape: for each type, a function from lists of that type to lists of that type. reverse satisfies map f . reverse = reverse . map f because it moves elements without looking at them. sort does not, because it compares them, so mapping first can change the order it produces. Identical signatures, different answers to an equation.
A drawn square against a commuting square.
Every naturality square can be drawn: the four arrows exist and their endpoints match by construction. Whether the two routes are the same arrow is a separate question, settled by evaluating both. Drawing establishes that the question is well posed, not that the answer is yes.
A check that could fail against one that could not.
Verifying naturality between two constant functors gives agreement at every arrow, and both routes reduce to the same arrow whatever the transformation, so no assignment could have failed. Verifying between functors that act differently on arrows is a check with a possible negative outcome. Only the second is evidence.
Common errors
Common misconception
That a mapping is a functor once it sends objects to objects and arrows to arrows with matching sources and targets. Those conditions make it a candidate; the composition law decides. In the worked example a mapping map that type-checks may still break map (g . f) = map g . map f, because the compiler enforces the types and not the laws.
Common misconception
That drawing the naturality square establishes naturality. Every such square can be drawn: the arrows
Related units
Requires
Connected
- Linear Transformations (analogous to)
Learn this topic
Used in
Sources
- Category Theory (2010)
- Category Theory for Programmers (2019)