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