Ответ 1
Хорошо, посмотрим 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
по заданному функтору тождества.