Прежде всего:
Любая монада также является аппликативным функтором, а любой аппликативный функтор - функтором.
Это верно в контексте Haskell, но (читается Applicative
как «сильный слабый моноидальный функтор») не в общем, по довольно тривиальной причине, по которой вы можете иметь «аппликативные» функторы между различными моноидальными категориями, тогда как монады (и комонады) являются эндофункторами ,
Кроме того, отождествление Applicative
с сильными слабыми моноидальными функторами немного вводит в заблуждение, поскольку для обоснования имени (и сигнатуры типа (<*>)
) требуется функтор между замкнутыми моноидальными категориями, который сохраняет как моноидальную структуру, так и внутренний гом . Это можно правдоподобно назвать «слабым замкнутым моноидальным функтором», за исключением того, что функтор между моноидальными замкнутыми категориями, который сохраняет одно свойство, сохраняет другое очевидным образом . Так Applicative
описывает только endofunctors на Hask сохранения моноидальных структур (,)
, его экземпляры получить много свойств автоматически, включая их силу , которые , таким образом , могут быть опущены.
Кажущаяся связь с Monad
, возможно, является артефактом неявных ограничений на Applicative
совпадение аспектов их соответствующих моноидных структур, счастливое совпадение, которое, к сожалению, не переживает дуализации.
Так же, как комонада категории является монадой на C o p , оплаксный моноидальный функтор C → D является слабым моноидальным функтором C o p → D o p . Но H a s k o p не является моноидально замкнутым , и кооперация , не включающая в себя применение функции, вряд ли заслуживает названия. В любом случае, результат не был бы ужасно интересным:ССо п С→ DСо п→ Dо пЧАСа с ко пApplicative
class (Functor f) => CoMonoidal f where
counit :: f () -> ()
cozip :: f (a, b) -> (f a, f b)
Applicative
ЧАСа с ко пnewtype Op b a = Op (a -> b)
ЧАСа с кб → аЧАСа с копOp b a
ЧАСа с к
ЧАСа с кApplicative
class (Functor f) => CoApplicative f where
copure :: f a -> a
coap :: (f a -> f b) -> f (a -> b)
Конечно, добавление duplicate :: f a -> f (f a)
к copure
будет производить комонаду (при условии соблюдения законов). Но нет очевидной связи между - coap
чем бы это ни было - и extend :: (f a -> b) -> f a -> f b
. При сравнении типов становится ясно, что дуализация происходит по-разному: комоноидальные структуры лежат в основе duplicate
и cozip
имеют мало общего друг с другом или с coap
(что, вероятно, в любом случае не имеет смысла), тогда как liftA2 (,)
и (<*>)
являются эквивалентными и могут быть получены из join
.
Другой возможный способ дуализации Applicative
, который имеет еще меньшее отношение к комадам, заключается в рассмотрении контравариантных моноидальных функторов:
class (Contravariant f) => ContraMonoidal f where
contraunit :: f a
contrazip :: f a -> f b -> f (Either a b)
ЧАСа с ко пb <~ a
contracurry :: (Either c b <~ a) -> (c <~ (b <~ a))
contraapply :: b -> Either a (a <~ b)
ЧАСа с кCoApplicative
Однако в моноидальной закрытой категории, более гостеприимной к дуализации, вам может повезти больше. В частности, я считаю, что обе Kleisli (Cont r)
и их противоположные категории моноидально замкнуты, так что это может быть лучшим контекстом для изучения этих идей.