9 puntos por bboydart91 2026-02-08 | 2 comentarios | Compartir por WhatsApp

Texto principal

  • Explica con código TypeScript el proceso que va desde los dos problemas que no pueden resolverse solo con map de los funtores (el problema de que una función quede atrapada dentro de un contenedor y el problema del anidamiento de contexto al componer) hasta llegar a los funtores aplicativos y las mónadas
  • Parte del trasfondo de 1988, cuando Eugenio Moggi modeló los programas no como A → B, sino como A → T(B)
  • Aborda la estructura flatMap = map + join y las tres leyes para usarla de forma segura (asociatividad, identidad izquierda e identidad derecha)
  • Explica por qué una mónada es un "objeto monoide en la categoría de endofuntores" comparándolo con el monoide de la suma de enteros
  • También menciona por qué Promise funciona de manera monádica, pero no es una mónada matemática en sentido estricto

Las limitaciones de los funtores: lo que no se puede hacer con map

  • Si se aplica una función currificada con map, el resultado deja la función atrapada dentro del contenedor, como Maybe<(b: number) => number>
    • map solo puede recibir funciones que están fuera del contenedor, así que no hay forma de aplicar esa función atrapada a otro valor
  • Si se componen dos funciones que devuelven un funtor, el contexto queda anidado como Maybe<Maybe>
    • A medida que aumentan los pasos, se anida indefinidamente como Maybe<Maybe<Maybe<...>>>

Funtores aplicativos: aplicar una función dentro del contenedor

  • Con la operación apply, es posible aplicar una función atrapada dentro de un contenedor al valor de otro contenedor
    • apply: T<(A → B)> → T<A> → T<B>
  • Con la operación pure, se inserta un valor puro en el contenedor
  • Límite: hay que tener definido de antemano qué contenedores se van a componer
    • No puede expresar dependencias secuenciales dinámicas en las que el siguiente cálculo se decide según el resultado del cálculo anterior

Mónadas: la invención de una operación para aplanar anidamientos

  • La operación join aplana un contenedor doble T<T<A>> → T<A> en uno solo
    • Array.prototype.flat de JavaScript cumple el mismo papel
  • En la práctica se usa flatMap, que combina map + join
    • flatMap: T<A> → (A → T<B>) → T<B>
    • map recibe A → B, pero flatMap recibe A → T<B>, de modo que el resultado se mantiene en una sola capa

Las tres leyes de flatMap

  • Ley de asociatividad: al aplanar un triple anidamiento T(T(T(A))), el resultado debe ser el mismo ya sea que se aplane desde adentro
    hacia afuera o desde afuera hacia adentro
    • m.flatMap(f).flatMap(g) === m.flatMap(x => f(x).flatMap(g))
  • Ley de identidad izquierda: si se mete un valor con pure y luego se aplica flatMap de inmediato, debe dar lo mismo que aplicar la función directamente
    • pure(a).flatMap(f) === f(a)
  • Ley de identidad derecha: si se pasa pure a flatMap, se obtiene el contenedor original
    • m.flatMap(pure) === m

Desglosando "objeto monoide en la categoría de endofuntores"

  • Los funtores en programación van del mundo de los tipos al mundo de los tipos, así que son endofuntores
  • Se puede construir una categoría de endofuntores donde los propios endofuntores sean los objetos
  • Si se sustituyen los requisitos de un monoide (operación binaria + ley de asociatividad + elemento identidad), queda así:
    • operación binaria = join
    • elemento identidad = pure
    • La estructura corresponde exactamente al monoide de la suma de enteros

Por qué Promise no es una mónada

  • then mezcla el comportamiento de map y flatMap según el valor de retorno
  • Un estado Promise<Promise> no está permitido en tiempo de ejecución y se fusiona inmediatamente en una sola capa
  • Aunque en la práctica es conveniente, no satisface las leyes de una mónada matemática

2 comentarios

 
calofmijuck 2026-02-08

¡Por favor, también aborden la comónada!

 
bboydart91 2026-02-09

Uaa... lo voy a pensar jajajaja