Лакс моноидальные функторы с другой моноидальной структурой
Аппликативные функторы хорошо известны и любимы среди хаскеллеров за их способность применять функции в эффективном контексте.
В терминах теории категорий можно показать, что методыApplicative
:
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
эквивалентны наличиюFunctor f
с операциями:
unit :: f ()
(**) :: (f a, f b) -> f (a,b)
идея заключается в том, чтобы написатьpure
вы просто замените()
вunit
с заданным значением, и написать(<*>)
Вы помещаете функцию и аргумент в кортеж, а затем сопоставляете подходящую функцию приложения.
Более того, эта переписка превращаетApplicative
законы в естественные моноидальные законы оunit
а также(**)
так что на самом деле аппликативный функтор - это именно то, что теоретик категорий назвал бы слабым моноидальным функтором (потому что(**)
это просто естественное преобразование, а не изоморфизм).
Хорошо, отлично, отлично. Это хорошо известно. Но это только одно семейство слабых моноидальных функторов - тех, которые уважают моноидальную структурутовар, Слабый моноидальный функтор включает в себя два варианта моноидальной структуры, в источнике и в пункте назначения: вот что вы получите, если превратить продукт в сумму:
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
один?