§ Natural Transformations as ends
- Bartosz: Natural transformations as ends
- Ends generalize the notion of product/limit. It's sort of like an infinite product plus the wedge condition.
- ∫Xpxx is the notation for ends, where p is a profunctor.
- Remember
dimap :: (a' -> a) -> (b -> b') -> p a b -> p a' b'
. Think of this as:
-----p a' b'-------
a' -> [a -> b] -> b'
--pab---
- The set of natural transformations is an end.
- Haskell:
type Nat f g = forall x. f x -> g x
. - We can think of this as the "diagonal" of some end
p x x
for some profunctor p
we need to cook up. -
type p f g a b = f a -> g b
. Is p f g
a profunctor?
dimap :: (a' -> a) -> (b -> b') -> (f a -> g b) -> (f a' -> g b')
dimap a'2a b2b' fa2gb = \fa' ->
let fa = fmap a'2a fa'
let gb = fa2gb fa
let gb' - fmap b2b' gb
in gb'
dimap a'2a b2b' fa2gb = (@fmap g b2b') . fa2gb . (@fmap f a'2a)
- Clearly, from the above implementation, we have a profunctor.
- So we have a profunctor
P(a, b) = C(Fa, Gb)
. - In haskell, the end is
End p = forall a. p a a
. - In our notation, it's
\int_x C(Fx, Gx)
. - Recall the wedge condition. For a profunctor
p: Cop x C -> C
, and any morphism k: a -> b
for a, b ∈ C
, the following diagram commutes for the end \int_X p(X,X)
:
(p x x, p y y, p z z, ... infinite product)
\int_x p(x,x)
/[πa] [πb]\
v v
p(a,a) p(b,b)
\ /
[p(id, k)] [p(k,id)]
\ /
v v
p a b
- If we replace
p x x
with with our concrete p a b = C(fa, gb)
, we get:
(forall x. f x -> g x)
/ \
[@ a] [@ b]
v v
τa:(f a -> g a) τb:(f b -> g b)
\ /
dimap id(a) k τa dimap k id(b) τb
\ /
\ τb.(@fmap f k): (f a-> g b)
\ /
\ COMMUTES?
\ /
(@fmap g k).τa(f a -> g b)
- This says that
gk . τa = τb . fk
- But this is a naturality condition for
τ
! - So every end corresponds to a natural transformation, and
τ
lives in [C, D](f, g)
. - This shows us that the set of natural transformations can be seen as an end (?)
- I can write
\int_a D(fa, ga) ~= [C, D](f, g)
§ Invoking Yoneda
- Now, yoneda tells us that
[C, Set](C(a, -), f(-)) ~= f(a)
. - Now I write the above in terms of ends as
\int_x Set(C(a, (x)), f(x)) ~= f(a)
. - So we can write this as a "point-full" notation!
- In haskell, this would be
forall x. (a -> x) -> f x ~= f a
.