Lectures onType Theory
Chapter 169
Chapter 169Optional

Profunctors, Coends, and Optics

Prerequisites. Direct starred prerequisites: none. No later core chapter depends on this route.

A configuration record has a field, and a program wants to read it and to replace it. Write S for the record type and A for the field type. The pair of operations is get:SA,put:S×AS, and every question in this chapter comes from asking what makes a particular pair a legitimate accessor and how two accessors compose.

Take S:=A×B with get:=pr1 and put((a,b),a):=(a,b). Now take the same S with get:=pr1 and put((a,b),a):=(a,b), which ignores the new value. Both pairs have the same type. The second is not an accessor, and saying why requires an equation, not a type: get(put(s,a))=a fails for it. A third pair, with put((a,b),a):=(a,b0) for a fixed b0, satisfies that equation and fails put(s,gets)=s. A fourth, storing a counter of how many writes have occurred, satisfies both and fails put(put(s,a),a)=put(s,a).

Definition 169.1 — Concrete lens and its laws

A lens from S to A is a pair get:SA and put:S×AS. It is lawful when get(put(s,a))=a,put(s,gets)=s,put(put(s,a),a)=put(s,a), called put-get, get-put and put-put.

Proposition 169.2 — Composition of lenses

Let (get1,put1) be a lens from S to A and (get2,put2) a lens from A to B. Then get:=get2get1,put(s,b):=put1(s,put2(get1s,b)) is a lens from S to B, and it is lawful when both are.

Proof of Proposition 169.2 — Composition of lenses

Proof. Put-get. get(put(s,b))=def.get2(get1put1(s,put2(get1s,b)))=putget1get2(put2(get1s,b))=putget2b.

Get-put. put(s,gets)=def.put1(s,put2(get1s,get2get1s))=getput2put1(s,get1s)=getput1s.

Put-put. Abbreviate a:=get1s. Then put(put(s,b),b)=def.put1put1(s,put2(a,b)), put2(get1put1(s,put2(a,b)),b)=putget1put1put1(s,put2(a,b)), put2(put2(a,b),b)=putput2put1put1(s,put2(a,b)), put2(a,b)=putput1put1(s,put2(a,b))=def.put(s,b). ◻

Three failures produced three laws, and the laws compose. The next paragraph produces the accessor that a lens cannot be.

Example 169.3 — A client that defeats the lens

Let S:=A+B and let a client wish to modify the left summand when it is present and leave the value alone otherwise. A get:SA does not exist: there is nothing to return at an element of B. The two operations that do exist are match:SA+S,build:AS, with match(inla)=inla, match(inrb)=inr(inrb) and build=inl. Such a pair is a prism, and it is lawful when match(builda)=inlaandmatchs=inla implies builda=s.

Example 169.4 — A client that defeats both

Let S be a list of A’s and let a client wish to replace every element. Neither a lens nor a prism applies: there is not one focus but many. The operation that exists is extract:SnNAn×(AnS), sending a list to its length, its elements, and the function rebuilding a list of that length. A traversal is such an operation. Its laws are stated in section 169.7 once the machinery that makes them short is available.

Three accessors with three shapes, three law sets, and no common composition. The rest of the chapter produces one definition covering all of them, one composition, and one notion of lawfulness, and proves that each specialises correctly.

Profunctors

Definition 169.5 — Profunctor

Let C be a category. A profunctor on C is a functor P:Cop×CSet. Concretely, P assigns a set P(A,B) to each pair of objects and a function dimap:homC(A,A)×homC(B,B)×P(A,B)P(A,B) satisfying dimap(idA,idB)=idP(A,B),dimap(f,g)dimap(f,g)=dimap(ff, gg).

The variance is forced by the intended reading: an element of P(A,B) is a transformation consuming an A and producing a B, so a map into the consumed position and a map out of the produced position both act on it, in opposite directions.

Example 169.6 — Four profunctors on

  1. Fun(A,B):=homSet(A,B), with dimap(f,g)(h):=ghf.

  2. ConstR(A,B):=R for a fixed set R, with dimap(f,g):=idR. This forgets both arguments.

  3. Tagged(A,B):=B, with dimap(f,g):=g. This uses only the produced position.

  4. KlT(A,B):=homSet(A,TB) for a monad T, with dimap(f,g)(h):=T(g)hf. Taking T:=()×W for a monoid W gives an effect-sensitive example: the transformation may also emit an element of W.

Each satisfies the two laws of definition 169.5: for item 1, both are associativity and unitality of composition; for item 2 both sides are the identity; for item 3 they are functoriality of the identity functor; for item 4 they are functoriality of T together with item 1.

Definition 169.7 — Strength for an accessor shape

Let (M,,I) be a monoidal category acting on C by :M×CC (definition 169.13). A Tambara structure for the action on a profunctor P is a family ζA,B,M:P(A,B)P(MA, MB) natural in A and B, dinatural in M, and satisfying ζA,B,I=P(λA1,λB),ζMA,MB,NζA,B,M=P(αN,M,A1,αN,M,B)ζA,B,NM, where λ and α are the unit and associativity data of the action.

Proposition 169.8 — Where the structure comes from

Take C:=Set.

  1. For the action MA:=M×A of (Set,×,{}), a Tambara structure on Fun is the operation hidM×h, which is exactly what the put of a lens applies to a modification of the focus.

  2. For the action MA:=M+A of (Set,+,), a Tambara structure on Fun is hidM+h, which is what the match of a prism applies on the branch where the focus is present.

  3. ConstR carries a Tambara structure for every action, namely the identity; Tagged carries one for the product action only after a choice of element of M, and none uniformly.

Proof of Proposition 169.8 — Where the structure comes from

Proof. For 1 and 2, the two equations of definition 169.7 are the unit and associativity coherences of the product and of the coproduct. For 3, the identity map makes both sides of each equation the identity; and a natural family BM×B would give, at B={}, an element of M natural in M, hence a natural transformation from the terminal object to the identity functor on Set, which does not exist since has no element. ◻

Proposition 169.8 is the answer to a question that library documentation usually leaves open: the classes named “strong” and “choice” are not stipulations but the two instances of definition 169.7 for the two monoidal actions that the two accessor shapes use.

Dinaturality, ends, and coends

Let P,Q:Cop×CSet. A transformation between them should be a family θA,B:P(A,B)Q(A,B), and naturality is the usual square. Now consider instead a family θA:P(A,A)Q(A,A), in which the same object occupies both positions. Attempting to state naturality for f:AB requires a square P(A,A) θA Q(A,A)P(B,B) θB Q(B,B) and neither vertical map exists: P is contravariant in the first argument and covariant in the second, so f induces P(B,A)P(A,A) and P(A,A)P(A,B), not a map P(A,A)P(B,B). The repair is to put the mixed object in the middle.

Definition 169.9 — Dinatural transformation

A dinatural transformation θ:PQ is a family θA:P(A,A)Q(A,A) such that for every f:AB the hexagon Q(f,idA)θAP(idA,f)=Q(idB,f)θBP(f,idB) : P(B,A)Q(A,B) commutes.

Definition 169.10 — End and coend

An end of P is an object AP(A,A) with a dinatural family πA:AP(A,A)P(A,A) universal among such: every dinatural family out of a constant factors uniquely through it. A coend is an object AP(A,A) with a dinatural family ιA:P(A,A)AP(A,A) universal among dinatural families into a constant.

Proposition 169.11 — Ends and coends in

Let C be small and P:Cop×CSet.

  1. AP(A,A) is the set of families (xA)A with xAP(A,A) such that P(idA,f)(xA)=P(f,idB)(xB) for every f:AB.

  2. AP(A,A) is the quotient of AP(A,A) by the equivalence relation generated by (A, P(f,idA)(y))  (B, P(idB,f)(y)) for f:AB and yP(B,A).

Proof of Proposition 169.11 — Ends and coends in

Proof. End. The displayed set carries the projections πA, and the condition is exactly the hexagon of definition 169.9 for a constant source, whose two composites reduce to the two sides of the displayed equation. A dinatural family out of a set X assigns x(θAx), which lands in the displayed set by dinaturality and is the unique factoring map.

Coend. The quotient carries the injections ιA, and the generating relation is exactly the identification the hexagon forces on the disjoint union. A dinatural family into a set Y identifies the two sides of every generating relation, hence factors through the quotient; the factoring is unique because the injections are jointly surjective. ◻

Lemma 169.12 — Yoneda reduction

For K:CSet and XC, ChomC(X,C)×KC  KX,C(homC(C,X)KC)  KX when K is contravariant in the second display.

Proof of Lemma 169.12 — Yoneda reduction

Proof. For the first, the map from left to right sends the class of (f,k) to K(f)(k); it is well defined because the generating relation of proposition 169.11 identifies (gf,k) with (f,K(g)(k)), and both have image K(gf)(k). Its inverse sends xKX to the class of (idX,x). One round trip is K(idX)=id; the other sends the class of (f,k) to the class of (idX,K(f)(k)), and those are identified by the generating relation at f. The second display is the same argument with the quotient replaced by the compatible-family description of proposition 169.11(1). ◻

Exercise 169.1

★★☆ Let C be the two-object category with objects 0,1, one non-identity map f:01, and let P(A,B):=homC(A,B).

  1. List the four sets P(A,B) and the disjoint union P(0,0)P(1,1).

  2. Compute the generating relation of proposition 169.11(2) explicitly and the resulting quotient.

  3. Compute AP(A,A) and say why the two answers differ in cardinality.

The monoidal action

Chapter 159 supplies a symmetric monoidal category (M,,I) with its associator, unitors and symmetry. An optic needs more: a way for M to act on the category C in which the data live. The two are different, and the difference is what allows a lens and a prism to be instances of one definition.

Definition 169.13 — Monoidal action

A monoidal action of (M,,I) on a category C consists of a functor :M×CC together with natural isomorphisms λA:IA  A,αN,M,A:(NM)A  N(MA), subject to the two coherence conditions: the pentagon αN,M,PAαNM,P,A=(idNαM,P,A)αN,MP,A(aN,M,PidA), where a is the associator of M, and the triangle (idMλA)αM,I,A=rMidA, where r is the right unitor of M.

Proposition 169.14 — Two actions on

  1. (Set,×,{}) acts on Set by MA:=M×A, with λ and α the evident bijections.

  2. (Set,+,) acts on Set by MA:=M+A, with λ and α the evident bijections.

Both satisfy definition 169.13.

Proof of Proposition 169.14 — Two actions on

Proof. In each case λ and α are bijections of finite constructions, and each coherence condition is an equation between two bijections built from the same components; following an arbitrary element through both sides gives the same result. For item 1 at the pentagon, an element (((n,m),p),a) is sent by both composites to (n,(m,(p,a))); for item 2, an element of a four-fold coproduct is sent by both composites to its copy in the corresponding summand. ◻

Remark 169.15 — An action is not an internal tensor

In proposition 169.14 the acting category happens to be Set again, and the action happens to be the monoidal product. Neither is required. Taking C to be the category of pointed sets and M to be (Set,×,{}) acting by M(A,a0):=(M×A,(m0,a0)) for a chosen m0 gives an action whose acting objects are not objects of C; the notion of definition 169.13 still applies, and no tensor on C is used. The distinction matters because the residual object of an optic will live in M, and quotienting over it is quotienting over acting objects, not over data.

Optics as a coend

Definition 169.16 — Optic

Fix an action of (M,,I) on C. For pairs of objects (S,S) and (A,A) of C, set Optic((S,S),(A,A)):=MMhomC(S,MA)×homC(MA,S). By proposition 169.11 this is the set of pairs (l,r) with l:SMA and r:MAS, quotiented by the relation generated by ((fidA)l, r)  (l, r(fidA)) for l:SMA, r:NAS and f:MN in M. Write lr for the class of (l,r) and call M its residual.

The residual is scratch space: information taken out of S that must be kept in order to rebuild S. Relation (169.1) says that no client may inspect it, since moving a map f from one side to the other does not change the optic.

Proposition 169.17 — Composition

The assignment l2r2l1r1:=(M1l2)l1 | r1(M1r2) is well defined and makes pairs of objects of C the objects of a category Optic, with id(S,S):=λS1λS.

Proof of Proposition 169.17 — Composition

Proof. Well-definedness. Replace the representative of the second optic by one related through f:M2N2. The composite changes by M1f, and (169.1) applied at M1M2M1N2 identifies the two composites, using α to rewrite M1(M2A) as (M1M2)A. Replacing the representative of the first optic is the same argument with fid on the outside.

Identity. For lr with residual M, lrλS1λS=def.(Il)λS1|λS(Ir)=λnaturalλMA1l|rλMA=(169.1)lr, the last step moving the isomorphism λ:IMM across, which is legal because it is a map of M. The other unit law is the same calculation on the other side.

Associativity. Choose representatives of three optics with residuals M1,M2,M3 simultaneously, which is legitimate because a coend in Set over a product of indices may be computed one index at a time. Both bracketings give the pair ((M1(M2l3))(M1l2)l1, r1(M1r2)(M1(M2r3))) after using α to associate the residual, and α is an isomorphism of M, so (169.1) identifies the two. ◻

Proposition 169.18 — Lenses are optics for the product action

For C:=Set with the action MA=M×A, Optic((S,S),(A,A))  homSet(S,A)×homSet(S×A,S), and the isomorphism sends lr to (pr2l, r(pr1l×idA)) and (get,put) to idS,getput.

Proof of Proposition 169.18 — Lenses are optics for the product action

Proof. Compute the coend: Mhom(S,M×A)×hom(M×A,S)Mhom(S,M)×hom(S,A)×hom(M×A,S)hom(S,A)×hom(S×A,S), The second step applies lemma 169.12 with X:=S and KM:=hom(S,A)×hom(M×A,S), which is covariant in M only through the second factor, contravariantly; the reduction therefore substitutes S for M. Tracing the two composites through the chain gives the displayed formulas. ◻

Proposition 169.19 — Prisms are optics for the coproduct action

For C:=Set with the action MA=M+A, Optic((S,S),(A,A))  homSet(S,A+S)×homSet(A,S).

Proof of Proposition 169.19 — Prisms are optics for the coproduct action

Proof. The same computation with + in place of ×: hom(M+A,S)hom(M,S)×hom(A,S) by the universal property of the coproduct, and then lemma 169.12 on the contravariant factor hom(M,S) substitutes for M, leaving hom(S,A+S)×hom(A,S). ◻

Remark 169.20 — A near miss

Suppose the quotient (169.1) is dropped and an optic is taken to be a pair (M,l,r) with the residual named. Composition can still be defined by the formula of proposition 169.17, but it depends on the representative: the two pairs ({}×M, ,l, rpr2)and(M, l, r) describe the same accessor and compose to pairs with residuals {}×M×N and M×N, which are different objects. The resulting structure is not a category, since its identities do not satisfy the unit law on the nose. The quotient is therefore not tidying: it is what makes composition well defined.

Exercise 169.2

★★☆ Take M to be the terminal monoidal category, with one object I and one map, acting on C by IA=A.

  1. Show that Optic((S,S),(A,A)) is then homC(S,A)×homC(A,S), and identify the accessor family this describes.

  2. Show that the quotient (169.1) is the identity relation in this case, and say which hypothesis of remark 169.20 therefore fails to bite.

  3. Give an action for which Optic((S,S),(A,A)) is the set of functions SS ignoring A and A entirely, and name the accessor family.

The profunctor representation

Definition 169.21 — The category of Tambara modules

Fix an action of M on C. Objects of Tamb are pairs (P,ζ) of a profunctor and a Tambara structure (definition 169.7); a morphism (P,ζ)(Q,ξ) is a natural transformation θ:PQ with ξA,B,MθA,B=θMA,MBζA,B,M. Write U:TambProf for the forgetful functor.

Definition 169.22 — The generated Tambara module

For a profunctor P define (ΦP)(X,Y):=MMC,DChomC(X,MC)×P(C,D)×homC(MD,Y), with the Tambara structure that reindexes the residual by N(). For the representable profunctor EA,A(C,D):=homC(C,A)×homC(A,D) this gives, by lemma 169.12 twice, (ΦEA,A)(X,Y)MhomC(X,MA)×homC(MA,Y)=Optic((X,Y),(A,A)).

Lemma 169.23 — Φ is left adjoint to U

Tamb(ΦP, T)Prof(P, UT), naturally.

Proof of Lemma 169.23 — Φ is left adjoint to U

Proof. A morphism ΦPT in Tamb is, by proposition 169.11, a family of functions out of the coend, that is a dinatural family hom(X,MC)×P(C,D)×hom(MD,Y)T(X,Y), compatible with the Tambara structures. Given θ:PUT, define it by sending (l,p,r) to T(l,r)(ξC,D,M(θC,Dp)), where ξ is the structure of T; compatibility with the structures is the second equation of definition 169.7 for ξ. Conversely, restricting a morphism ΦPT along M:=I and l,r the unitors gives a natural transformation PUT, and the two constructions are mutually inverse by the unit equation of definition 169.7 and the coend relation. ◻

Theorem 169.24 — Profunctor representation

For all objects S,S,A,A of C, Optic((S,S),(A,A))  (P,ζ)Tamb(P(A,A)P(S,S)), the end being the set of families tP:P(A,A)P(S,S) natural in P over Tamb.

Proof of Theorem 169.24 — Profunctor representation

Proof. Proof idea. Both sides are computed by Yoneda: the right-hand side is a set of natural transformations out of an evaluation functor, and lemma 169.23 identifies that evaluation functor with a representable one, whose representing object is the optic set of definition 169.22.

Write evA,A:=(U)(A,A):TambSet. By lemma 169.23 at P:=EA,A and the Yoneda lemma in Prof, Tamb(ΦEA,A, T)Prof(EA,A, UT)(UT)(A,A)=evA,A(T), so evA,A is represented by ΦEA,A. Hence P(evA,A(P)evS,S(P))=repr.P(Tamb(ΦEA,A,P)evS,S(P))=YonedaevS,S(ΦEA,A), and the last set is Optic((S,S),(A,A)) by definition 169.22. ◻

Corollary 169.25 — Both directions, explicitly

Let p=lr with l:SMA and r:MAS. The corresponding family is p~P:=P(l,r)ζA,A,M. Conversely, a family t is determined by its component at ΦEA,A, and that component is determined by its value at λA1λA, which recovers lr.

Proof of Corollary 169.25 — Both directions, explicitly

Proof. The displayed formula is the image of p under the two isomorphisms of theorem 169.24, read off from the Yoneda step. The converse is the content of the same two isomorphisms taken in the other direction: the Yoneda isomorphism evaluates a natural family at the identity, which here is λA1λA. ◻

Remark 169.26 — Rank polymorphism is not enough

The right-hand side of theorem 169.24 is an end over Tamb, that is a family natural in the Tambara module. A programming language encodes it as a rank-two polymorphic type Optic A A S S := P. Tamb(P)PAAPSS, and the encoding is faithful only to the extent that inhabitants of the polymorphic type are natural. Chapter 6 supplies the exact statement: for the polymorphic calculus considered there, the abstraction theorem gives, for each closed term of the displayed type, the relational condition at every relation between two instances of P, and instantiating it at the graph of a Tambara morphism yields naturality. Two hypotheses are needed and neither is automatic in a real language: that the language admits the abstraction theorem, and that the constraint Tamb(P) is interpreted so that its relational condition is exactly compatibility with the structure maps. Where either fails, the polymorphic type has inhabitants that are not optics; example 169.29 exhibits one.

Lawfulness

Definition 169.27 — Lawful optic

For an optic p=lr:(S,S)(A,A) with residual M define outside(p):=rl:SS,once(p):=lidMAr,twice(p):=lrlr, the last two being elements of the two-hole optic set M1,M2hom(S,M1A)×hom(M1A,M2A)×hom(M2A,S). The optic p is lawful when outside(p)=idS and once(p)=twice(p).

Theorem 169.28 — Lawfulness specialises to the lens laws

For the product action on Set, an optic (S,S)(A,A) corresponding under proposition 169.18 to (get,put) is lawful in the sense of definition 169.27 if and only if the three laws of definition 169.1 hold.

Proof of Theorem 169.28 — Lawfulness specialises to the lens laws

Proof. Proof idea. Compute the two-hole optic set by the same two moves as in proposition 169.18 and read off what the two conditions say.

Take l=idS,get and r=put, the representative supplied by proposition 169.18, with residual S.

Outside. outside(p)=putidS,get, whose value at s is put(s,gets). Equality with idS is get-put.

The two-hole set. Applying the universal property of the product and lemma 169.12 twice, as in proposition 169.18, gives M1,M2hom(S,M1×A)×hom(M1×A,M2×A)×hom(M2×A,S)hom(S,A)×hom(S×A,A)×hom(S×A,S), the three components being the first read, the second read after the first write, and the final write.

Once and twice. Under that isomorphism, once(p) has components (get, pr2, put) and twice(p) has components (get, getput, put(put×idA)δ), where δ duplicates the state component. Equality of the second components is get(put(s,a))=a, which is put-get; equality of the third is put(put(s,a),a)=put(s,a), which is put-put. Conversely the three laws give the two equalities by the same reading. ◻

Example 169.29 — An inhabitant that is not a lawful optic

Take S:=A×B and get:=pr1, put((a,b),a):=(a,b0) for a fixed b0B with B having at least two elements. By proposition 169.18 this is an element of Optic((S,S),(A,A)), hence by theorem 169.24 a natural family over Tamb, hence an inhabitant of the polymorphic type of remark 169.26. By theorem 169.28 it is not lawful: get-put fails at any (a,b) with bb0. Naturality is therefore strictly weaker than lawfulness, and no amount of parametricity supplies the missing equations.

Proposition 169.30 — Lawful optics compose

If p:(S,S)(A,A) and q:(A,A)(B,B) are lawful then so is qp.

Proof of Proposition 169.30 — Lawful optics compose

Proof. Write p=l1r1 and q=l2r2 with residuals M1,M2.

Outside. outside(qp)=proposition169.17r1(M1r2)(M1l2)l1=outside(q)=idr1l1=outside(p)=ididS.

Once and twice. Both sides of once(qp)=twice(qp) expand, by the same composition formula applied inside the two-hole set, into expressions in which the inner occurrence is once(q) or twice(q) and the outer one is once(p) or twice(p). Substituting the two hypotheses turns the second expression into the first. ◻

Proposition 169.31 — Lawfulness specialises to the prism laws

For the coproduct action on Set, an optic corresponding under proposition 169.19 to (match,build) is lawful if and only if match(builda)=inla and matchs=inla implies builda=s.

Proof of Proposition 169.31 — Lawfulness specialises to the prism laws

Proof. As in theorem 169.28, with the coproduct computation of proposition 169.19 in place of the product one. The condition outside(p)=idS becomes: the composite that matches and then rebuilds is the identity, which is the second displayed law. The condition once(p)=twice(p) becomes: matching a built value returns that value, which is the first. ◻

Traversals

Example 169.4 left a shape without an action. It has one.

Definition 169.32 — The traversal action

Let M be the category of applicative functors on Set and natural transformations respecting the applicative structure, with the composition of applicative functors and I the identity functor. Let it act on Set by FA:=FA. The unit and associativity isomorphisms of definition 169.13 are the identities of functor composition.

Proposition 169.33 — Traversals are optics for that action

For the action of definition 169.32, Optic((S,S),(A,A))  F(hom(A,FA)hom(S,FS)), the end over applicative functors. For S a list type and A its element type, an element of the right-hand side is exactly an operation traverse:F:(AFA)(SFS) natural and applicative-preserving in F.

Proof of Proposition 169.33 — Traversals are optics for that action

Proof. The displayed isomorphism is theorem 169.24 for this action, after observing that a Tambara module for it is exactly a profunctor with a strength for every applicative functor, and that the end over Tamb reduces to the end over M by evaluating at the representable Tambara modules of definition 169.22. The reading of the right-hand side as traverse is corollary 169.25 with P taken to be KlF of example 169.6(4). ◻

Remark 169.34 — The exact traversal boundary

Proposition 169.33 identifies traversals with optics for the applicative action. Two further statements belong to their sources and are not proved here. The first is that traversable functors are exactly the finitary containers, so that the coend of definition 169.16 for this action is the coproduct over arities displayed in example 169.4; this is the theorem of Jaskelioff and O’Connor, and Proposition 169.33 does not establish it. The second is the composition of optics across different actions — a lens after a traversal, say — which requires a comparison between the two acting categories. Román treats that case and its concrete profunctor interpretation [Rom20], and the general mixed and enriched setting, in which the forward and backward directions live in different categories, is the subject of Clarke, Elkins, Gibbons, Loregian, Milewski, Pillmore and Román. Nothing in definition 169.16proposition 169.31 covers a mixed optic: both l and r there are morphisms of the same C.

Example 169.35 — A client that needs different directions

Let the forward direction be a function SMA in Set and the backward direction a function MAS that may fail, that is a map in the Kleisli category of the partiality monad. No single C contains both as morphisms with the composition of proposition 169.17: composing two backward maps must compose two partial functions, and composing a forward with a backward map must not. The repair is to let the two hom-sets in definition 169.16 be taken in two different categories, both acted on by M, which is the definition of a mixed optic.

Boundary

Proved here. The concrete lens laws and their composition (definition 169.1, proposition 169.2); profunctors and four examples (definition 169.5, example 169.6); the Tambara structure and its origin in the two accessor shapes (definition 169.7, proposition 169.8); dinaturality, ends and coends with the explicit description in Set (definition 169.9, proposition 169.11, lemma 169.12); the monoidal action and two instances (definition 169.13, proposition 169.14); the optic coend, its composition, and the specialisations to lenses and prisms (definition 169.16, proposition 169.17, proposition 169.18, proposition 169.19); the near miss when the quotient is dropped (remark 169.20); the representation theorem in both directions (lemma 169.23, theorem 169.24, corollary 169.25); lawfulness with its two specialisations and its composition (definition 169.27, theorem 169.28, proposition 169.31, proposition 169.30); an inhabitant that is not lawful (example 169.29); and traversals as optics for the applicative action (proposition 169.33).

Owned elsewhere. The identification of traversable functors with finitary containers, the composition of optics across different actions, and the mixed and enriched settings, as recorded in remark 169.34. The modular library encoding and its executable baseline are due to Pickering, Gibbons and Wu; the optic category and the notion of lawfulness used in definition 169.27 are Riley’s.

Not a foundation. Nothing above changes the ambient type theory. Optics are a construction inside a category, and the chapter’s role is to give existential types, variance, profunctors and monoidal actions a proof-bearing application. It is not a survey of accessor libraries, and no library encoding is treated as evidence for a theorem: example 169.29 is the standing reminder that a well-typed inhabitant of the encoding need not be an accessor.

Suggested first pass.

Problems exercise 169.3, exercise 169.4, and exercise 169.6 form the suggested first pass. None of these problems is a prerequisite for a later chapter.

Exercise 169.3

★★☆ A setter is an operation over:(AA)(SS).

  1. Find a monoidal action for which Optic((S,S),(A,A)) is the set of setters, and verify the two coherence conditions of definition 169.13.

  2. Compute the coend for that action as in proposition 169.18, displaying each use of lemma 169.12.

  3. State what definition 169.27 says for a setter, and show that it is equivalent to over(id)=id together with over(f)over(g)=over(fg).

Exercise 169.4

★★★ Theorem 169.24 was proved by two applications of Yoneda.

  1. Write out lemma 169.23 in full, checking that the constructed transformation respects the Tambara structures and that the two constructions are mutually inverse.

  2. Give the direction from an optic to a natural family without appealing to the theorem, by exhibiting p~P of corollary 169.25 and checking naturality directly.

  3. Give the direction back, and check that the round trip through λA1λA is the identity.

  4. Identify the step at which the smallness of C is used, and say what replaces it when C is large.

Exercise 169.5

★★★ Example 169.35 exhibits a client needing two categories.

  1. Write the definition of a mixed optic: two categories C,D acted on by one M, and the coend MhomC(S,MA)×homD(MA,S).

  2. Show that the composition of proposition 169.17 is still well defined, and identify which of its three verifications now uses two actions rather than one.

  3. Exhibit a mixed composition that a same-category encoding rejects, taking D to be the Kleisli category of the partiality monad, and state which typing constraint fails in the same-category version.

Exercise 169.6

★★★ Practical project.optic-law-corpus Implement, in Agda, the optic hierarchy of this chapter together with a law corpus, and run a data update through the profunctor representation and back.

Calculus to implement. The profunctor interface of definition 169.5; the Tambara structures of definition 169.7 for the product action and the coproduct action; the representation maps of corollary 169.25 in both directions; the concrete lens, prism and setter representations of proposition 169.18, proposition 169.19 and exercise 169.3; the composition of proposition 169.17; and decidable checks for the three lens laws, the two prism laws, and the two setter laws. Represent an optic in the concrete form and convert to the profunctor form only where a composition requires it.

Invariant. Each conversion must be a round trip: converting a concrete optic to its profunctor form and back must return the original, and the program must check that equation for every optic it constructs. That check is the executable form of corollary 169.25. Composition must be performed in the profunctor form and the result converted back, so that proposition 169.30 is exercised rather than assumed.

Concrete result. For a nested record value, a report giving: the value before and after an update performed through a composite optic; the round-trip check for each optic used; and the verdict of each law check, positive or negative, with the witness when negative.

Acceptance test. Use the record S:=A×(B×C) with A=B=C=2, the first-component lens p on S, the first-component lens q on B×C, and the composite qp obtained through the profunctor form. Updating (tt,(tt,tt)) through qp with the constant-ff modification must give (tt,(ff,tt)), and the round-trip check must pass for p, q and the composite. The prism of example 169.3 on 2+2 must pass both prism laws, and its composition with p must be rejected by the type checker, since the shapes do not match. The unlawful lens of example 169.29 must pass the round-trip check and fail the get-put check, with the failing pair printed; that pair of outcomes is the executable form of the separation between naturality and lawfulness. Produce three mutations that still typecheck — drop the residual quotient by fixing a residual, use pr1 where pr2 is required in the lens conversion, and omit the applicative-preservation condition from the traversal structure — and confirm that each makes a named case fail. State explicitly that the program checks the laws at finitely many values and proves neither theorem 169.24 nor theorem 169.28.

Search the book

Type to search the local edition.