Profunctor Equipment in Haskell

g0xA52A2A1 pts0 comments

Profunctor Equipment in Haskell |   Bartosz Milewski's Programming Cafe

Home

About

Bartosz Milewski's Programming Cafe

Category Theory, Haskell, Concurrency, C++

May 16, 2026

Profunctor Equipment in Haskell

Posted by Bartosz Milewski under Category Theory, Haskell, Programming | Tags: Category Theory, Haskell, Profunctor Equipment |

[2] Comments

Previously: Profunctor Equipment.

To make things more palatable for programmers, I decided to provide a toy implementation of some of the equipments in Haskell. The advantage of this encoding is that it can be verified by the compiler, and I still trust the compiler more than I trust the AI.

A more adequate implementation would require a full-blown dependently typed language, but if we restrict ourselves to just a single category and work only with endo-functors and endo-profunctors, we can get at least some intuitions. If you want to see a more elaborate version, see the proarrows library by Sjoerd Visscher.

The only 0-cell I’ll be using is the Haskell category of types and functions. For vertical 1-cells I’ll use the standard library implementation of Functor, and for horizontal ones I’ll use Profunctor.

A 2-cell in :

is implemented as a natural transformation:

type Cell f g h j = forall a c . h a c -> j (f a) (g c)

The forall serves as a universal quantifier.

The horizontal composition of such cells is given by:

hcomp :: (Functor f, Functor f', Functor g, Functor g'<br>, Profunctor h, Profunctor j, Profunctor k) =><br>Cell f g h j -> Cell f' g' j k<br>-> Cell (Compose f' f) (Compose g' g) h k<br>hcomp fg_hj fg_jk hac = dimap getCompose Compose $ fg_jk (fg_hj hac)

I used the library definition of functor composition:

newtype Compose f g a = Compose { getCompose :: f (g a) }

Vertical composition of cells uses a more elaborate profunctor composition:

vcomp :: (Functor f, Functor g, Functor h<br>, Profunctor p, Profunctor q, Profunctor r, Profunctor s) =><br>Cell f g p r -> Cell g h q s<br>-> Cell f h (Procompose q p) (Procompose s r)<br>vcomp fg_pr gh_qs (Procompose qxc pax)<br>= Procompose (gh_qs qxc) (fg_pr pax)

Profunctor composition is defined using a coend. In Haskell, we implement a coend:

as an existential type:

data Procompose p q d c where<br>Procompose :: p x c -> q d x -> Procompose p q d c

Here, x is a type that’s not in the argument list, so it’s interpreted using the existential counterpart of forall.

This is the horizontal unit cell:

type Hunit p = Cell Identity Identity p p

hUnit :: Profunctor p => Hunit p<br>hUnit = dimap runIdentity Identity

and here’s its vertical counterpart:

type Vunit f a b = Cell f f (->) (->)

vUnit :: Functor f => Vunit f a b<br>vUnit = fmap

I used the library implementation of the Identity functor, and the type constructor (->) for the hom-profunctor–the unit of profunctor composition. The unit laws are satisfied up to isomorphism.

The companion and the conjoint are synonyms of the library types Costar and Star:

newtype Star f d c = Star { runStar :: d -> f c }<br>newtype Costar f d c = Costar { runCostar :: f d -> c }

type Companion f d c = Costar f d c<br>type Conjoint f d c = Star f d c

The companion unit and counit cells:

are given by, respectively:

type CompUnit f = Cell Identity f (->) (Costar f)

compUnit :: Functor f => CompUnit f<br>compUnit h = Costar (fmap (h . runIdentity))

and

type CompCoUnit f = Cell f Identity (Costar f) (->)

compCoUnit :: Functor f => CompCoUnit f<br>compCoUnit (Costar h) = Identity . h

Similarly for the conjoint:

type ConjUnit f = Cell f Identity (->) (Star f)

conjUnit :: Functor f => ConjUnit f<br>conjUnit h = Star (fmap (Identity . h))

and:

type ConjCoUnit f = Cell Identity f (Star f) (->)

conjCoUnit :: Functor f => ConjCoUnit f<br>conjCoUnit (Star h) = h . runIdentity

More advanced constructions would require the definition of categories internal to Hask and the use of dependent types.

Haskell code is available here.

Share this:

Share on Reddit (Opens in new window)<br>Reddit

More

Share on X (Opens in new window)

Share on LinkedIn (Opens in new window)<br>LinkedIn

Share on Facebook (Opens in new window)<br>Facebook

Email a link to a friend (Opens in new window)<br>Email

Like this:<br>Like Loading…

Related

2 Responses to "Profunctor Equipment in Haskell"

0x1 Says:

May 16, 2026 at 3:23 am

That’s great! Wonderful

Loading...

0x1 Says:

May 16, 2026 at 3:23 am

Thank you for having given a code example :-}

Loading...

Leave a ReplyCancel reply

Archived Entry

Post Date :

May 16, 2026 at 2:47 am

Category :

Category Theory, Haskell, Programming

Tags: Category Theory, Haskell, Profunctor Equipment<br>Do More :

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

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

Loading Comments...

Write a Comment...

Email (Required)

Name (Required)

Website

%d

profunctor cell functor haskell type identity

Related Articles