Подтвердить что ты не робот

Хаскелл: Как присоединиться к естественной трансформации?

Я могу определить естественное преобразование в Haskell как:

h :: [a] -> Maybe a
h []    = Nothing
h (x:_) = Just x

и с функцией k:

k :: Char -> Int
k = ord

условие естественности выполняется из-за того, что:

h . fmap k == fmap k . h

Можно ли продемонстрировать аналогичным образом условие естественности функции List monad join? У меня возникли проблемы с пониманием того, что join, скажем, concat в частности, является естественным преобразованием.

4b9b3361

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