Аппликативные законы для формулировок альтернативного класса

Известная альтернативная формулировка 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)

Мне немного любопытно, хорошо ли это (или что-то подобное) для чего-то.

Ответ 1

Это очень аккуратная идея!

Я полагаю, что свободная теорема для fcomp равна

fcomp (fmap (post .) u) (fmap (. pre) v) = fmap (\f -> post . f . pre) (fcomp u v)