Eu venho de um background em C #, onde o LINQ evoluiu para o Rx.NET, mas sempre teve algum interesse no FP. Após algumas introduções às mônadas e alguns projetos paralelos em F #, eu estava pronto para tentar avançar para o próximo nível.
Agora, depois de várias palestras sobre a mônada livre de pessoas de Scala e vários artigos escritos em Haskell, ou F #, eu encontrei gramáticas com intérpretes para a compreensão serem bastante semelhantes a IObservable
cadeias.
No FRP, você compõe uma definição de operação a partir de blocos menores específicos de domínio, incluindo efeitos colaterais e falhas que permanecem dentro da cadeia, e modela seu aplicativo como um conjunto de operações e efeitos colaterais. Na mônada livre, se eu entendi corretamente, você faz o mesmo fazendo suas operações como functores e levantando-as usando coyoneda.
Quais seriam as diferenças entre os dois que inclinam a agulha em direção a qualquer uma das abordagens? Qual é a diferença fundamental ao definir seu serviço ou programa?
fonte
Cont
é a única mônada que vi sugerida que não pode ser expressa através da mônada livre, é provável que se possa supor que o FRP possa ser. Como pode quase qualquer outra coisa .IObservable
é uma instância da mônada de continuação.Respostas:
Mônadas
Uma mônada consiste em
Um endofuncor . Em nosso mundo de engenharia de software, podemos dizer que isso corresponde a um tipo de dados com um único parâmetro de tipo irrestrito. Em C #, isso seria algo da forma:
Duas operações definidas sobre esse tipo de dados:
return
/pure
pega um valor "puro" (ou seja, umT
valor) e o "envolve" na mônada (ou seja, produz umM<T>
valor). Comoreturn
é uma palavra-chave reservada em C #, usareipure
para me referir a essa operação a partir de agora. Em C #,pure
seria um método com uma assinatura como:bind
/flatmap
pega um valor monádico (M<A>
) e uma funçãof
.f
pega um valor puro e retorna um valor monádico (M<B>
). A partir disso,bind
produz um novo valor monádico (M<B>
).bind
tem a seguinte assinatura C #:Além disso, para ser uma mônada,
pure
ebind
são obrigados a obedecer às três leis da mônada.Agora, uma maneira de modelar mônadas em C # seria construir uma interface:
(Observação: para manter as coisas breves e expressivas, usarei algumas liberdades com o código ao longo desta resposta.)
Agora podemos implementar mônadas para tipos de dados concretos implementando implementações concretas de
Monad<M>
. Por exemplo, podemos implementar a seguinte mônada paraIEnumerable
:(Estou usando intencionalmente a sintaxe LINQ para chamar o relacionamento entre a sintaxe LINQ e as mônadas. Mas observe que poderíamos substituir a consulta LINQ por uma chamada para
SelectMany
.)Agora, podemos definir uma mônada para
IObservable
? Parece que sim:Para ter certeza de que temos uma mônada, precisamos provar as leis da mônada. Isso pode não ser trivial (e eu não estou familiarizado o suficiente com o Rx.NET para saber se eles podem ser provados apenas a partir da especificação), mas é um começo promissor. Para facilitar o restante desta discussão, vamos apenas assumir que as leis de mônada são válidas nesse caso.
Mônadas grátis
Não existe uma "mônada livre" singular. Em vez disso, mônadas livres são uma classe de mônadas que são construídas a partir de functores. Ou seja, dado um functor
F
, podemos derivar automaticamente uma mônada paraF
(isto é, a mônada livre deF
).Functors
Como mônadas, os functores podem ser definidos pelos três itens a seguir:
Duas operações:
pure
agrupa um valor puro no functor. Isso é análogo apure
uma mônada. De fato, para os functores que também são mônadas, os dois devem ser idênticos.fmap
mapeia valores na entrada para novos valores na saída através de uma determinada função. Sua assinatura é:Como mônadas, os functores são obrigados a obedecer às leis dos functores.
Semelhante às mônadas, podemos modelar functors através da seguinte interface:
Agora, como as mônadas são uma subclasse de functores, também podemos refatorar
Monad
um pouco:Aqui eu adicionei um método adicional,,
join
e forneci implementações padrão de ambosjoin
ebind
. Observe, no entanto, que essas são definições circulares. Então você teria que substituir pelo menos um ou outro. Além disso, observe quepure
agora é herdado deFunctor
.IObservable
e Mônadas GrátisAgora, como definimos uma mônada para
IObservable
e como as mônadas são uma subclasse de functores, segue-se que devemos ser capazes de definir uma instância de functor paraIObservable
. Aqui está uma definição:Agora que temos um functor definido
IObservable
, podemos construir uma mônada livre a partir desse functor. E é exatamente assim queIObservable
se relaciona com as mônadas livres - a partir da qual podemos construir uma mônada livreIObservable
.fonte