Хорошо, давайте посмотрим на concat
.
Во-первых, вот реализация:
concat :: [[a]] -> [a]
concat = foldr (++) []
Это соответствует структуре вашего h
, где Maybe
заменяется на []
и, что еще более важно, []
заменяется на - для ненадлежащего использования синтаксиса - [[]]
.
Конечно,
[[]]
также является функтором, но это , а не Functor
экземпляр того, как его использует условие естественности. Перевод вашего примера напрямую не сработает:
concat . fmap k
= / = fmap k . concat
... потому что оба fmap
работают только с самым внешним []
.
И хотя [[]]
является гипотетически допустимым экземпляром Functor
, вы не можете сделать его напрямую, по практическим причинам, которые, вероятно, очевидны.
Однако вы можете восстановить правильный подъем следующим образом:
concat . (fmap . fmap) k
== fmap k . concat
... где fmap . fmap
эквивалентно реализации fmap
для гипотетического Functor
экземпляра для [[]]
.
В качестве связанного дополнения, return
неудобно по противоположной причине: a -> f a
- естественное преобразование из функтора исключенной идентичности. Используя : []
, идентичность будет записана так:
(:[]) . ($) k
== fmap k . (:[])
... там, где совершенно лишнее ($)
стоит за то, что будет fmap
над элитным функтором идентичности.