The optics Haskell package is an alternative to the famous lens package.

lens uses a van Laarhoven encoding, encoding lenses as functions. This means than not only do lens lenses form a category, but they actually compose using standard function composition. In other words, they can compose using the old-fashioned . operator, even before the Category typeclass.

optics, in contrast, defines lenses using opaque newtypes. It should still be possible to get access to composition via the . operator by defining a Category instance. However, optics doesn't do that, but instead defines a new % composition operator. The docs have this to say:

The (.) operator from Control.Category cannot be used to compose optics [..] because it would not support type-changing optics or composing optics of different kinds.


optics must use a different composition operator (%). Optic does not quite form a Category, thanks to type-changing optics.

This leaves me very puzzled. It is well known that lens' van Laarhoven lenses do support type-changing (polymorphic update), whilst still being a category by construction, via their underlying function type.

Can someone explain why it's impossible for optics lenses to form a category, even though they are functionally equivalent to van Laarhoven?

Is it possible to define lenses more opaque than lens whilst still forming a lawful category?


1 Answer 1


optics do form a category where the objects are (Type, Type). However, the Optic type is defined with

newtype Optic k is s t a b = ...

The domain and the codomain of Optic are curried into 4 type arguments s t a b, but the Category typeclass in Haskell requires the domain and the codomain to be the last two type arguments of the type constructor.

Alternatively, the Optic type can be defined with

newtype Optic k is (st :: (Type, Type)) (ab :: (Type, Type)) = ...

This allows a Category instance, however it is less user-friendly, since the user would need to use DataKinds tuples to specify the types.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.