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:
This parallels the structure of your
hwhereMaybeis 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 aFunctorinstance 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 ofFunctoryou 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 . fmapis equivalent to the implementation offmapfor a hypotheticalFunctorinstance for[[]].As a related addendum,
returnis awkward for the opposite reason:a -> f ais 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 befmapover the elided identity functor.