Funitores monoidais relaxados com uma estrutura monoidal diferente
Os functores aplicáveis são bem conhecidos e amados entre os Haskellers, por sua capacidade de aplicar funções em um contexto eficaz.
Em termos teóricos da categoria, pode ser demonstrado que os métodos deApplicative
:
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
são equivalentes a ter umFunctor f
com as operações:
unit :: f ()
(**) :: (f a, f b) -> f (a,b)
a ideia é que escreverpure
você acabou de substituir o()
nounit
com o valor fornecido e escrever(<*>)
você esmaga a função e o argumento em uma tupla e mapeia uma função de aplicação adequada sobre ela.
Além disso, essa correspondência transforma oApplicative
leis em leis naturais mono-ish sobreunit
e(**)
, portanto, de fato, um functor aplicativo é precisamente o que um teórico de categorias chamaria de functor monoide laxista (lax porque(**)
é apenas uma transformação natural e não um isomorfismo).
Ok, ótimo, ótimo. Isso é bem conhecido. Mas essa é apenas uma família de funcionadores monoidais relaxados - aqueles que respeitam a estrutura monoidal doprodutos. Um functor monoidal relaxado envolve duas opções de estrutura monoidal, na origem e no destino: eis o que você obtém se transformar o produto em soma:
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
Parece que transformar soma em outras estruturas monoidais se torna menos interessante porunit :: Void -> f Void
sendo determinado de maneira exclusiva, então você realmente tem mais semigrupos. Mas ainda:
Applicative
1?