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 fmap
s (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 fmap
s 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,
fmap^5 == (<.>)
fmap^n == fmap^(n+4) -- forall `n >= 6`
So yeah, that’s some curious tidbit.