Прежде всего:
Любая монада также является аппликативным функтором, а любой аппликативный функтор - функтором.
Это верно в контексте 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 <~ acontracurry :: (Either c b <~ a) -> (c <~ (b <~ a))contraapply :: b -> Either a (a <~ b)
ЧАСа с кCoApplicative
Однако в моноидальной закрытой категории, более гостеприимной к дуализации, вам может повезти больше. В частности, я считаю, что обе Kleisli (Cont r)и их противоположные категории моноидально замкнуты, так что это может быть лучшим контекстом для изучения этих идей.