Haskell: Как присоединиться к естественной трансформации? - PullRequest
19 голосов
/ 09 мая 2011

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

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

и с помощью функции k:

k :: Char -> Int
k = ord

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

h . fmap k == fmap k . h

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

1 Ответ

16 голосов
/ 09 мая 2011

Хорошо, давайте посмотрим на 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 над элитным функтором идентичности.

...