Existe um conceito de algo como functores coaplicativos sentados entre comônadas e functores?

17

Qualquer mônada também é um função aplicadora e qualquer função aplicadora é um função. Além disso, qualquer comonada é um functor. Existe um conceito semelhante entre comônadas e functores, algo como functor co-aplicativo e quais são suas propriedades?

FunctorsFunctorsFunções aplicáveis???MônadasComonads

Atualização: eu também estaria interessado em possíveis usos desse conceito.

Petr Pudlák
fonte
Tem certeza de que não estava procurando Comonads -> ??? -> Co-funcionadores?
Josias
11
@josiah Não, até onde eu sei, as comonadas são funcionárias , não co-funcionárias.
Petr Pudlák
11
Não é divisível essa peça que falta?
Gus

Respostas:

15

Em primeiro lugar:

Qualquer mônada também é um função aplicadora e qualquer função aplicadora é um função.

Isso é verdade no contexto de Haskell, mas (lendo Applicativecomo "forte função monoidal relaxada") não geralmente, pela razão bastante trivial de que você pode ter funções "aplicativas" entre diferentes categorias monoidais, enquanto mônadas (e comônadas) são endofuncionadoras .

Além disso, identificar-se Applicativecom fortes funcionadores monoidais frouxos é um pouco enganador, porque justificar o nome (e a assinatura do tipo (<*>)) requer um funcionamento entre categorias monoidais fechadas que preserva a estrutura monoidal e o hom interno . Isso poderia ser plausivelmente chamado de "função monoidal fechada frouxa", exceto que um função entre categorias fechadas monoidais que preserva uma propriedade preserva a outra da maneira óbvia . Como Applicativedescreve apenas endofuncionadores em Hask preservando a estrutura monoidal de (,), suas instâncias ganham muitas propriedades automaticamente, incluindo sua força , que pode ser elidida.

A aparente conexão com Monadé sem dúvida um artefato das limitações implícitas em Applicativefazer com que aspectos de suas respectivas estruturas monóides coincidam, uma feliz coincidência que infelizmente não sobrevive à dualização.

Apenas como um comonad numa categoria é um mônade em C o p , uma oplax monoidal functor C D é um relaxado monoidal functor C o pD O p . Mas H um s k o P é não monoidal fechada , e um co que não incluem a aplicação de função quase méritos do nome. De qualquer forma, o resultado não seria muito interessante:CCop CDCopDopHumaskopApplicative

class (Functor f) => CoMonoidal f where
    counit :: f () -> ()
    cozip :: f (a, b) -> (f a, f b)

Poderíamos imaginar uma noção de "colax closed functor", que pareceria muito mais Applicativese existisse. Infelizmente, não é (para o melhor do meu conhecimento) um círculo fechado em tudo: em H uma s k corresponde ao morphisms b um em H uma s k o P , mas não funciona como um hom interno lá - porque as setas são invertidas, algum tipo de co-função seria necessária, o que não podemos definir em geral para H a s k .Humaskopnewtype Op b a = Op (a -> b)HumaskbumaHumaskopOp b aHumask

Se simplesmente fingirmos que "os functores fechados colax" existiam para e, além disso, funcionasse da maneira que esperávamos ingenuamente, um co- baseado nisso provavelmente seria assim:HumaskApplicative

class (Functor f) => CoApplicative f where
    copure :: f a -> a
    coap :: (f a -> f b) -> f (a -> b)

Adicionar duplicate :: f a -> f (f a)a copureisso produziria uma comonada (supondo que as leis sejam cumpridas), é claro. Mas não existe uma relação óbvia entre coap- o que quer que seja - e extend :: (f a -> b) -> f a -> f b. Comparando os tipos torna-se claro que a dualização está acontecendo de maneiras diferentes: as estruturas comonoidal subjacente duplicatee coziptêm pouco a ver um com o outro ou com coap(que provavelmente não faz sentido de qualquer maneira), enquanto liftA2 (,)e (<*>)são equivalentes e podem ser derivadas de join.

Outra maneira possível de dualizar Applicative, que tem ainda menos a ver com comônadas, é considerar os funcionamentos monoidais contravariantes:

class (Contravariant f) => ContraMonoidal f where
    contraunit :: f a
    contrazip :: f a -> f b -> f (Either a b)

Mas este colide contra as mesmas questões como acima, ou seja, que não é um círculo fechado. Se fosse, teríamos algum tipo de tal forma que podemos escrever funções como e e assim por diante que realmente funcionou como esperado.Humaskopb <~ acontracurry :: (Either c b <~ a) -> (c <~ (b <~ a))contraapply :: b -> Either a (a <~ b)

HumaskCoApplicative

No entanto, em uma categoria fechada monoidal mais hospitaleira à dualização, você pode ter melhor sorte. Em particular, acredito que ambos Kleisli (Cont r)e sua categoria oposta são fechados monoidalmente, de modo que possa ser um contexto melhor para explorar essas idéias.

CA McCann
fonte
Comparando sua resposta a cstheory.stackexchange.com/a/22302/989 , é surpreendente que você não dualize produtos em somas. Claro, você está certo que Hask não tem somas categóricas; mas se você deseja restringir à categoria de programas totais (como no Agda), vamos fingir que está definido por enquanto, esse problema desaparece. (Não estou dizendo que Set ^ op é monoidal fechado, mas suspeito que o que estou dizendo implica).
Blaisorblade 21/02
8

Em este post sobre SO eu encontrei uma resposta interessante - functors decisivos . Se substituirmos ()por Void, (,)por Either e inverter as setas, obtemos:

class Functor f => Decisive f where
    nogood :: f Void -> Void
    orwell :: f (Either s t) -> Either (f s) (f t)

O post do blog também fornece algumas leis às quais os decisores decisivos aderem.

E, cada um Comonadé também Decisive:

instance Comonad c => Decisive c where
    nogood = counit
    orwell story = case counit story of
                     Left s  -> fmap (either id (const s)) story
                     Right t -> fmap (either (const t) id) story 

Portanto, os decisores decisivos se encaixam entre os functores e as comônadas, assim como os aplicadores se encaixam entre os functores e as mônadas.

Petr Pudlák
fonte
6

McBride e Patterson (Seção 7) mostram que um função aplicadora, também conhecida como expressão idiomática, é uma função monoidal forte e relaxada . Você está procurando um functor monolateral forte colax, também conhecido como um functor monoidal oplax forte . Como mencionado em um comentário, um functor monoidal oplax é um functor monoidal frouxo entre as categorias opostas, que acaba sendo uma versão comonoidal de um functor monoidal frouxo.

Desenhe os diagramas, inverta as setas!

Eu precisaria gastar um pouco de tempo trabalhando nos detalhes para ver qual é e traduzi-lo em uma noção de programação funcional.

Dave Clarke
fonte
Por alguma razão, o termo padrão parece ser "oplax monoidal functor". A idéia é um functor monoidal frouxo entre as categorias opostas, que acaba sendo uma versão comonoidal de um functor monoidal frouxo. O uso de "colax comonoidal" é redundante ou equivalente a "lax monoidal".
CA McCann
Eu exagerei no "co" -ing. Eu vou consertar minha resposta.
Dave Clarke