Yeah, this does not really fit the “Show and Tell” category, but neither does it others, so maybe you’ll forgive this chatter here.
Maybe this is part of Haskell folklore and seasoned veterans will know this curious tidbit, but I was quite surprised – and it was by no means obvious for me:
The type of fmap fmap fmap fmap fmap is quite interesting and even useful:
GHCI> :t fmap fmap fmap fmap fmap
fmap fmap fmap fmap fmap
:: Functor f => (b -> c) -> (a -> b) -> f a -> f c
So, for (<.>) = fmap fmap fmap fmap fmap, we essentially have function composition and application inside a functor.
With
f :: a -> b
g :: b -> c
c :: [a]
We can write
g <.> f $ a -- :: [c]
Also, I was quite surprised that a five-times fmap produces such a “clean” and immediately human-interpretable type. Any other syntactical sequence of fmaps (like three, four; then six or more) result in a rather garbled and less immediately easily-to-understand signatures, so the five-sequence (four-times-applied) fmap came as a real surprise:
Generally, sequentially applied fmaps will result in more Functor constraints than one.
Also it goes into a cycle after six repetitions of fmap, with a cycle of 4, so, with pseudo-operator ^ for self-application,
Interesting, indeed. I’d say the following is a complete catalog of interesting fmap sequences:
1x fmap :: Functor f => (a -> b) -> f a -> f b
3x fmap :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
5x fmap :: Functor f => (b -> c) -> (a -> b) -> f a -> f c
8x/12x/16x/… fmap :: (Functor f, Functor g, Functor h) => (a -> b) -> f (g (h a)) -> f (g (h b))
The others on the list besides 5x are all essentially fmap for composed functors, so I wouldn’t call them less easy to understand! I agree with you both that the 5x version is surprising, and that the cycle at the end is surprising as well.