Home

Home

About

About

Bartosz Milewski's Programming Cafe

Bartosz Milewski's Programming Cafe

June 30, 2026

Actegories

Category Theory

Haskell

Actegories

Category Theory

Haskell

Lens

Optics

Leave a Comment

Previously: Kan Extensions in Double Categories.

Kan Extensions in Double Categories

In programming, actegories play a central role in optics: lenses, prisms, traversals, etc. To understand actegories, let’s start with the definition of a monoidal category.

Monoidal Category

A monoidal category is a category equipped with a tensor product. A tensor product is a functor . We assume that this product is associative and unital– up to isomorphism. It means that there is an invertible associator:

\mathbf M

\otimes \colon \mathbf M \times \mathbf M \to \mathbf M

\alpha_{a, b, c} \colon (a \otimes b) \otimes c \to a \otimes (b \otimes c)

natural in all three arguments. We also have a unit object and two (invertible, natural) unitors:

1

\lambda_a \colon 1 \otimes a \to a

\rho_a \colon a \otimes 1 \to a

To get a better feel for it, we can try to model a monoidal category in Haskell. We parameterize it by the type of the tensor product, ten, which we want to be a Bifunctor:

The standard way to define a subcategory of Hask is to restrict the types of objects by imposing a constraint. Such a restriction has a special kind, Constraint:

A common example of such a constraint is a typeclass. For instance Monoid will restrict the objects of the category to be monoids. (In principle, we should also restrict the type of arrows, here to monoid morphisms.)

We can specify the unit of a monoidal category as an associated type (parameterized by ten):

The unit should be an object of the category, so it should satisfy the constraint. We can encode this in our definition as a precondition: obj (Unit ten). This leads to a circularity, which we can overcome using the language pragma UndecidableSuperClasses:

Finally, we can add the associator and the unitors (and their inverses):

Notice the obj constraints in the type of these functions and the infix notation for the tensor.

Let’s work out a few examples. The simplest is the category of all types with a cartesian product as tensor.

We define Hask using an empty class, and we make all objects its instances:

Similarly, we can define a monoidal category with Either as the tensor product, or with Monoid as the object constraint.

Actegory

An actegory is a category that supports the action of a monoidal category. You may think of it as “multiplying” or “scaling” the objects of this category by objects of the monoidal category. The (left) action can be defined as a functor from the product category to :

C

\triangleright \colon \mathbf M \times C \to C

or, after currying, as a functor from to the endofunctor category:

\mathbf M

![\triangleright \colon \mathbf M \to [C, C]](https://s0.wp.com/latex.php?latex=%5Ctriangleright+%5Ccolon+%5Cmathbf+M+%5Cto+%5BC%2C+C%5D&bg=ffffff&fg=29303b&s=0&c=20201002)

The coherency conditions are the invertible natural transformations that relate the action to the tensor product and its unit :

\triangleright

\otimes

1

\alpha_{m n a} \colon (m \otimes n) \triangleright a \to m \triangleright (n \triangleright a)

\lambda_{a} \colon 1 \triangleright a \to a

The action is functorial in both arguments, so our Haskell translation pegs it, for simplicity, as a Bifunctor. (A Profunctor action is also possible. Categorically, it would correspond to using as the monoidal category.)

\mathbf M^{op}

Another simplifying assumption is that the action uniquely identifies the tensor product, encoded here as the functional dependency act -> ten.

The simplest example of an actegory is the self action of the cartesian product. Here, the monoidal category acts on itself:

Monoidal Functors

Actegories that use the same monoidal category for their actions form a category. The morphisms in this category are (strict) monoidal functors. These are functors that map one action to another:

f (m \triangleright_1 a) \cong m \triangleright _2 f a

In Haskell, we can model them as:

In fact, actegories form a bicategory, with action-preserving natural transformations acting between monoidal functors.

Here’s an interesting example of a monoidal functor between non-trivial actegories:

Haskell code is available here.

here

Share this:

Share on Reddit (Opens in new window)

Reddit

[Share on Reddit (Opens in new window)

Reddit](https://bartoszmilewski.com/2026/06/30/actegories/?share=reddit)

More

More

Share on X (Opens in new window)

X

[Share on X (Opens in new window)

X](https://bartoszmilewski.com/2026/06/30/actegories/?share=twitter)

Share on LinkedIn (Opens in new window)

LinkedIn

[Share on LinkedIn (Opens in new window)

LinkedIn](https://bartoszmilewski.com/2026/06/30/actegories/?share=linkedin)

Share on Facebook (Opens in new window)

Facebook

[Share on Facebook (Opens in new window)

Facebook](https://bartoszmilewski.com/2026/06/30/actegories/?share=facebook)

Email a link to a friend (Opens in new window)

Email

[Email a link to a friend (Opens in new window)

Email](mailto:?subject=%5BShared%20Post%5D%20Actegories&body=https%3A%2F%2Fbartoszmilewski.com%2F2026%2F06%2F30%2Factegories%2F&share=email)

Like this:

Related

Leave a ReplyCancel reply

Cancel reply

Archived Entry

Post Date :

June 30, 2026 at 4:45 am

Category :

Category Theory, Haskell

Category Theory

Haskell

Tags: Actegories, Category Theory, Haskell, Lens, Optics

Actegories

Category Theory

Haskell

Lens

Optics

Do More :

You can leave a response, or trackback from your own site.

leave a response

trackback

Powered by WordPress.com.

Powered by WordPress.com

Discover more from   Bartosz Milewski's Programming Cafe

Subscribe now to keep reading and get access to the full archive.

Type your email…

Subscribe

Continue reading

Continue reading