Известная альтернативная формулировка Applicative
(см., например, Typeclassopedia) составляет
class Functor f => Monoidal f where
unit :: f ()
pair :: f a -> f b -> f (a, b)
Это приводит к законам, которые больше похожи на типичные законы идентичности и ассоциативности, чем на то, что вы получаете от Applicative
, но только тогда, когда вы работаете через пары-reassociating изоморфизмы. Размышляя об этом несколько недель назад, я придумал две другие формулировки, которые позволяют избежать этой проблемы.
class Functor f => Fapplicative f where
funit :: f (a -> a)
fcomp :: f (b -> c) -> f (a -> b) -> f (a -> c)
class Functor f => Capplicative f where
cunit :: Category (~>) => f (a ~> a)
ccomp :: Category (~>) => f (b ~> c) -> f (a ~> b) -> f (a ~> c)
Легко реализовать Capplicative
с помощью Applicative
, Fapplicative
с помощью Capplicative
и Applicative
с помощью Fapplicative
, поэтому все они имеют эквивалентную мощность.
Законы идентичности и ассоциативности совершенно очевидны. Но Monoidal
нужен закон естественности, и это тоже нужно. Как я могу их сформулировать? Также: Capplicative
, кажется, предлагает немедленное обобщение:
class (Category (~>), Functor f) => Appish (~>) f where
unit1 :: f (a ~> a)
comp1 :: f (b ~> c) -> f (a ~> b) -> f (a ~> c)
Мне немного любопытно, хорошо ли это (или что-то подобное) для чего-то.