Аппликативные функторы хорошо известны и хорошо любимы среди Haskellers за их способность применять функции в эффективном контексте.
В теоретико-множественных терминах можно показать, что методы Applicative
:
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
эквивалентны наличию a Functor f
с операциями:
unit :: f ()
(**) :: (f a, f b) -> f (a,b)
идея состоит в том, что для написания pure
вы просто заменяете ()
в unit
заданным значением, а для записи (<*>)
вы хлюпаете функцию и аргумент в кортеж, а затем сопоставляете подходящую функцию приложения над ним.
Более того, это соответствие превращает законы Applicative
в естественные моноидальные законы о unit
и (**)
, поэтому на самом деле аппликативный функтор - это то, что теоретик категории назвал бы слабым моноидальным функтором (lax, потому что (**)
является просто естественным преобразованием, а не изоморфизмом).
Хорошо, отлично, отлично. Это хорошо известно. Но это только одно семейство слабых моноидальных функторов - тех, которые относятся к моноидальной структуре продукта. Слабый моноидальный функтор включает в себя два варианта моноидальной структуры в источнике и предназначении: вот что вы получаете, если вы превращаете продукт в сумму:
class PtS f where
unit :: f Void
(**) :: f a -> f b -> f (Either a b)
-- some example instances
instance PtS Maybe where
unit = Nothing
Nothing ** Nothing = Nothing
Just a ** Nothing = Just (Left a)
Nothing ** Just b = Just (Right b)
Just a ** Just b = Just (Left a) -- ick, but it does satisfy the laws
instance PtS [] where
unit = []
xs ** ys = map Left xs ++ map Right ys
Кажется, что превращение суммы в другие моноидальные структуры становится менее интересным, поскольку unit :: Void -> f Void
определяется однозначно, поэтому вы действительно имеете больше полугруппы. Но все же:
- Существуют ли другие слабые моноидальные функторы, подобные описанным выше или полезным?
- Есть ли опрятная альтернативная презентация для них, например,
Applicative
one?