9 pontos por bboydart91 2026-02-08 | 2 comentários | Compartilhar no WhatsApp

Texto

  • Explica com código TypeScript o caminho que parte de dois problemas que não podem ser resolvidos apenas com o map de 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 como A → T(B)
  • Aborda a estrutura flatMap = map + join e 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 Promise funciona 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 como Maybe<(b: number) => number>, ou seja, a função fica presa dentro do contêiner
    • map só 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<...>>>

Funtor aplicativo: aplicar funções dentro do contêiner

  • A operação apply permite aplicar a uma valor em outro contêiner uma função presa dentro de um contêiner
    • apply: T<(A → B)> → T<A> → T<B>
  • A operação pure insere 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 join achata um contêiner duplo em um único, de T<T<A>> → T<A>
    • O Array.prototype.flat do JavaScript cumpre o mesmo papel
  • Na prática, usa-se flatMap, que combina map + join
    • flatMap: T<A> → (A → T<B>) → T<B>
    • map recebe A → B, mas flatMap recebe A → 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 dentro
    • m.flatMap(f).flatMap(g) === m.flatMap(x => f(x).flatMap(g))
  • Lei da identidade à esquerda: se você coloca um valor com pure e em seguida aplica flatMap, o resultado é igual a aplicar a função diretamente
    • pure(a).flatMap(f) === f(a)
  • Lei da identidade à direita: se passar pure para flatMap, o contêiner original é preservado
    • m.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

Por que Promise não é uma mônada

  • then mistura o comportamento de map e flatMap dependendo 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

 
calofmijuck 2026-02-08

Por favor, abordem também Comonad!

 
bboydart91 2026-02-09

Aah... vou pensar nisso kkkkk