"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > Introducción a la programación funcional en JavaScript: hacer mónadas #12

Introducción a la programación funcional en JavaScript: hacer mónadas #12

Publicado el 2024-08-25
Navegar:709

Introduction to Functional Programming in JavaScript: Do monads #12

En la programación funcional, las mónadas proporcionan una forma de manejar los cálculos de una manera estructurada y predecible. Entre varias mónadas, Do Monad (también conocida como "notación Do" o "comprensión de mónada") es una construcción poderosa que permite un manejo más legible y de estilo imperativo de las operaciones monádicas.

¿Qué es Do Mónada?

Do Monad es un azúcar sintáctico que simplifica el trabajo con mónadas al permitirle escribir secuencias de operaciones monádicas en un estilo que se asemeja a la programación imperativa. En lugar de encadenar operaciones con .then o .flatMap, Do Monad le permite escribir código más sencillo y legible.

Beneficios de la Do Monada

  1. Legibilidad: Permite escribir operaciones monádicas complejas de forma limpia y lineal.
  2. Estilo imperativo: proporciona una forma de expresar cálculos monádicos en un estilo familiar para quienes están acostumbrados a la programación imperativa.
  3. Manejo de errores: Simplifica el manejo de errores en operaciones monádicas al proporcionar una estructura clara y consistente.

Implementación de Do Monad en JavaScript

Si bien JavaScript no tiene soporte integrado para Do Monad como Haskell, podemos implementar una construcción similar usando funciones de generador y un ejecutor personalizado.

Ejemplo: implementación de un Do Monad Runner

Comencemos implementando un corredor Do Monad que pueda manejar mónadas Promise.

function* doGenerator() {
  const a = yield Promise.resolve(1);
  const b = yield Promise.resolve(2);
  const c = yield Promise.resolve(a   b);
  return c;
}

function runDo(genFunc) {
  const iter = genFunc();

  function handle(result) {
    if (result.done) return Promise.resolve(result.value);
    return Promise.resolve(result.value).then(res => handle(iter.next(res)));
  }

  return handle(iter.next());
}

// Usage
runDo(doGenerator).then(result => console.log(result)); // 3

En este ejemplo, doGenerator es una función generadora que genera promesas. La función runDo ejecuta el generador, maneja cada promesa obtenida y pasa el valor resuelto nuevamente al generador.

Aplicaciones prácticas de la mónada Do

Do Monad se puede utilizar en varios escenarios donde las operaciones monádicas deben secuenciarse de manera legible y mantenible.

Ejemplo: manejo de operaciones asincrónicas

Mejoremos el ejemplo anterior para manejar operaciones asincrónicas más complejas.

function* fetchUserData() {
  const user = yield fetch('https://api.example.com/user/1').then(res => res.json());
  const posts = yield fetch(`https://api.example.com/user/${user.id}/posts`).then(res => res.json());
  const firstPost = posts[0];
  const comments = yield fetch(`https://api.example.com/posts/${firstPost.id}/comments`).then(res => res.json());
  return { user, firstPost, comments };
}

runDo(fetchUserData).then(result => console.log(result));

En este ejemplo, fetchUserData es una función generadora que genera promesas para obtener datos del usuario, sus publicaciones y comentarios en la primera publicación. La función runDo ejecuta estas operaciones asincrónicas de forma legible y estructurada.

Ejemplo: Manejo de valores opcionales con Maybe Monad

También podemos usar el patrón Do Monad con otras mónadas como Maybe.

class Maybe {
  constructor(value) {
    this.value = value;
  }

  static of(value) {
    return new Maybe(value);
  }

  map(fn) {
    return this.value === null || this.value === undefined ? Maybe.of(null) : Maybe.of(fn(this.value));
  }

  flatMap(fn) {
    return this.value === null || this.value === undefined ? Maybe.of(null) : fn(this.value);
  }
}

function* maybeDoGenerator() {
  const a = yield Maybe.of(1);
  const b = yield Maybe.of(2);
  const c = yield Maybe.of(a   b);
  return c;
}

function runMaybeDo(genFunc) {
  const iter = genFunc();

  function handle(result) {
    if (result.done) return Maybe.of(result.value);
    return result.value.flatMap(res => handle(iter.next(res)));
  }

  return handle(iter.next());
}

// Usage
const result = runMaybeDo(maybeDoGenerator);
console.log(result); // Maybe { value: 3 }

En este ejemplo, mayDoGenerator es una función generadora que funciona con la mónada Maybe. La función runMaybeDo ejecuta el generador, maneja cada valor Maybe generado y pasa el valor desenvuelto nuevamente al generador.

Do Monad es una poderosa construcción que simplifica el trabajo con mónadas al permitirle escribir secuencias de operaciones monádicas en un estilo más legible e imperativo. Al implementar un corredor Do Monad, puede manejar operaciones asincrónicas complejas, valores opcionales y otros cálculos monádicos de una manera estructurada y fácil de mantener.

Si bien JavaScript no admite de forma nativa la sintaxis de Do Monad, al utilizar funciones de generador y ejecutores personalizados, puede lograr una funcionalidad similar. Este enfoque mejora la legibilidad y el mantenimiento de su código, lo que facilita el trabajo con operaciones monádicas en un estilo de programación funcional.

Declaración de liberación Este artículo se reproduce en: https://dev.to/francescoagati/introduction-to-functional-programming-in-javascript-do-monads-12-362a?1 Si hay alguna infracción, comuníquese con [email protected] para borrarlo
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3