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.
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 fmap
s 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With