Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell: How is join a natural transformation?

I can define a natural transformation in Haskell as:

h :: [a] -> Maybe a
h []    = Nothing
h (x:_) = Just x

and with a function k:

k :: Char -> Int
k = ord

the naturality condition is met due to the fact that:

h . fmap k == fmap k . h

Can the naturality condition of the List monad's join function be demonstrated in a similar way? I'm having some trouble understanding how join, say concat in particular, is a natural transformation.

like image 271
user2023370 Avatar asked May 08 '11 23:05

user2023370


1 Answers

Okay, let's look at concat.

First, here's the implementation:

concat :: [[a]] -> [a]
concat = foldr (++) []

This parallels the structure of your h where Maybe is replaced by [] and, more significantly, [] is replaced by--to abuse syntax for a moment--[[]].

[[]] is a functor as well, of course, but it's not a Functor instance in the way that the naturality condition uses it. Translating your example directly won't work:

concat . fmap k =/= fmap k . concat

...because both fmaps are working on only the outermost [].

And although [[]] is hypothetically a valid instance of Functor you can't make it one directly, for practical reasons that are probably obvious.

However, you can reconstruct the correct lifting as so:

concat . (fmap . fmap) k == fmap k . concat

...where fmap . fmap is equivalent to the implementation of fmap for a hypothetical Functor instance for [[]].

As a related addendum, return is awkward for the opposite reason: a -> f a is a natural transformation from an elided identity functor. Using : [] the identity would be written as so:

(:[]) . ($) k == fmap k . (:[])

...where the completely superfluous ($) is standing in for what would be fmap over the elided identity functor.

like image 70
C. A. McCann Avatar answered Nov 03 '22 08:11

C. A. McCann