Funtores, funtores aplicativos e mônadas em TypeScript
(evan-moon.github.io)Texto
- Explica com código TypeScript o caminho que parte de dois problemas que não podem ser resolvidos apenas com o
mapde um funtor (o problema de a função ficar presa dentro do contêiner e o problema do aninhamento de contexto na composição) até chegar a funtores aplicativos e mônadas - Começa pelo contexto em que, em 1988, Eugenio Moggi modelou programas não como
A → B, mas comoA → T(B) - Aborda a estrutura
flatMap = map + joine três leis para usá-la com segurança (associatividade, identidade à esquerda e identidade à direita) - Explica por que a mônada é um "objeto monoidal na categoria dos endofuntores" em contraste com o monoide da soma de inteiros
- Também menciona por que
Promisefunciona de forma monádica, mas não é uma mônada matemática em sentido estrito
Limites do funtor: o que não dá para fazer com map
- Se uma função curryficada for aplicada com
map, o resultado vira algo comoMaybe<(b: number) => number>, ou seja, a função fica presa dentro do contêinermapsó pode receber funções de fora do contêiner, então não há como aplicar a outra valor uma função que ficou presa dentro dele
- Ao compor duas funções que retornam um funtor, o contexto fica aninhado, como em
Maybe<Maybe>- À medida que as etapas aumentam, isso vira um aninhamento infinito do tipo
Maybe<Maybe<Maybe<...>>>
- À medida que as etapas aumentam, isso vira um aninhamento infinito do tipo
Funtor aplicativo: aplicar funções dentro do contêiner
- A operação
applypermite aplicar a uma valor em outro contêiner uma função presa dentro de um contêinerapply: T<(A → B)> → T<A> → T<B>
- A operação
pureinsere um valor puro no contêiner - Limite: é preciso definir antecipadamente quais contêineres serão compostos
- Não é possível expressar dependência sequencial dinâmica, em que o próximo cálculo é decidido com base no resultado anterior
Mônada: a invenção da operação que achata o aninhamento
- A operação
joinachata um contêiner duplo em um único, deT<T<A>> → T<A>- O
Array.prototype.flatdo JavaScript cumpre o mesmo papel
- O
- Na prática, usa-se
flatMap, que combinamap + joinflatMap: T<A> → (A → T<B>) → T<B>maprecebeA → B, masflatMaprecebeA → T<B>, mantendo o resultado com apenas uma camada
As três leis do flatMap
- Lei da associatividade: ao achatar um aninhamento triplo
T(T(T(A))), o resultado deve ser o mesmo tanto faz achatar de dentro para fora quanto de fora para dentrom.flatMap(f).flatMap(g) === m.flatMap(x => f(x).flatMap(g))
- Lei da identidade à esquerda: se você coloca um valor com
puree em seguida aplicaflatMap, o resultado é igual a aplicar a função diretamentepure(a).flatMap(f) === f(a)
- Lei da identidade à direita: se passar
pureparaflatMap, o contêiner original é preservadom.flatMap(pure) === m
Decompondo "objeto monoidal na categoria dos endofuntores"
- Em programação, um funtor vai do mundo dos tipos para o próprio mundo dos tipos, portanto é um endofuntor
- É possível construir uma categoria de endofuntores em que os próprios endofuntores são os objetos
- Aplicando os requisitos de um monoide (operação binária + lei da associatividade + elemento identidade), temos:
- operação binária =
join - elemento identidade =
pure - a estrutura corresponde exatamente ao monoide da soma de inteiros
- operação binária =
Por que Promise não é uma mônada
thenmistura o comportamento demapeflatMapdependendo do valor de retorno- O estado
Promise<Promise>não é permitido em tempo de execução e é imediatamente combinado em uma única camada - Embora seja conveniente na prática, não satisfaz as leis de uma mônada matemática
2 comentários
Por favor, abordem também Comonad!
Aah... vou pensar nisso kkkkk