"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: diferentes mónadas #11

Introducción a la programación funcional en JavaScript: diferentes mónadas #11

Publicado el 2024-07-29
Navegar:266

Introduction to Functional Programming in JavaScript: Different monads #11

Las mónadas son un concepto fundamental en la programación funcional que proporciona una forma de manejar cálculos y transformaciones de datos de forma estructurada. Hay varios tipos de mónadas, cada una diseñada para resolver problemas específicos y manejar diferentes tipos de datos y efectos.

¿Qué es una mónada?

Una mónada es una abstracción que permite el encadenamiento de operaciones sobre valores ajustados. Se define por tres propiedades principales:

  1. Unidad (también llamada de o retorno): una función que toma un valor y lo envuelve en una mónada.
  2. Enlazar (también llamado flatMap o cadena): una función que toma un valor monádico y una función que devuelve una mónada, aplica la función al valor ajustado y devuelve una nueva mónada.
  3. Asociatividad: La composición de las operaciones monádicas debe ser asociativa.

Tipos comunes de mónadas

  1. Quizás Mónada
  2. Cualquiera de las mónadas
  3. Mónada Promesa
  4. Lista de mónadas
  5. Mónada lectora
  6. Mónada del escritor
  7. Mónada estatal

1. Quizás mónada

Maybe Monad se utiliza para manejar valores opcionales. Representa un cálculo que podría fallar o devolver un valor nulo o indefinido.

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

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

  isNothing() {
    return this.value === null || this.value === undefined;
  }

  map(fn) {
    return this.isNothing() ? this : Maybe.of(fn(this.value));
  }

  flatMap(fn) {
    return this.isNothing() ? this : fn(this.value);
  }
}

// Usage
const maybeValue = Maybe.of('hello')
  .map(str => str.toUpperCase())
  .flatMap(str => Maybe.of(`${str} WORLD`));
console.log(maybeValue); // Maybe { value: 'HELLO WORLD' }

2. Cualquiera de las mónadas

Cualquiera de las mónadas se utiliza para manejar cálculos que pueden devolver un valor de éxito (derecha) o un valor de error (izquierda).

Implementación
class Either {
  constructor(value, isRight = true) {
    this.value = value;
    this.isRight = isRight;
  }

  static right(value) {
    return new Either(value, true);
  }

  static left(value) {
    return new Either(value, false);
  }

  map(fn) {
    return this.isRight ? Either.right(fn(this.value)) : this;
  }

  flatMap(fn) {
    return this.isRight ? fn(this.value) : this;
  }
}

// Usage
const rightValue = Either.right(5)
  .map(x => x   1)
  .flatMap(x => Either.right(x * 2));
console.log(rightValue); // Either { value: 12, isRight: true }

const leftValue = Either.left('error')
  .map(x => x   1)
  .flatMap(x => Either.right(x * 2));
console.log(leftValue); // Either { value: 'error', isRight: false }

3. Mónada Promesa

Promise Monad se utiliza para manejar cálculos asincrónicos.

Uso
const fetchData = url => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`Data from ${url}`);
    }, 1000);
  });
};

// Usage
fetchData('https://api.example.com')
  .then(data => {
    console.log(data); // 'Data from https://api.example.com'
    return fetchData('https://api.example.com/2');
  })
  .then(data => {
    console.log(data); // 'Data from https://api.example.com/2'
  })
  .catch(error => {
    console.error(error);
  });

4. Lista de mónadas

La mónada de lista se utiliza para manejar cálculos que producen una lista de valores.

Implementación
class List {
  constructor(values) {
    this.values = values;
  }

  static of(values) {
    return new List(values);
  }

  map(fn) {
    return List.of(this.values.map(fn));
  }

  flatMap(fn) {
    return List.of(this.values.flatMap(value => fn(value).values));
  }
}

// Usage
const list = List.of([1, 2, 3])
  .map(x => x   1)
  .flatMap(x => List.of([x, x * 2]));
console.log(list); // List { values: [ 2, 4, 3, 6, 4, 8 ] }

5. Mónada lectora

Reader Monad se utiliza para manejar cálculos que dependen de algún entorno o configuración compartido.

Implementación
class Reader {
  constructor(fn) {
    this.fn = fn;
  }

  static of(value) {
    return new Reader(() => value);
  }

  map(fn) {
    return new Reader(env => fn(this.fn(env)));
  }

  flatMap(fn) {
    return new Reader(env => fn(this.fn(env)).fn(env));
  }

  run(env) {
    return this.fn(env);
  }
}

// Usage
const config = { baseURL: 'https://api.example.com' };

const fetchUser = new Reader(env => `${env.baseURL}/user`);
const fetchPosts = new Reader(env => `${env.baseURL}/posts`);

const fetchUserAndPosts = fetchUser.flatMap(userURL =>
  fetchPosts.map(postsURL => ({ userURL, postsURL }))
);

console.log(fetchUserAndPosts.run(config)); 
// { userURL: 'https://api.example.com/user', postsURL: 'https://api.example.com/posts' }

6. Mónada del escritor

Writer Monad se utiliza para manejar cálculos que producen un valor junto con un registro o datos adicionales.

Implementación
class Writer {
  constructor(value, log) {
    this.value = value;
    this.log = log;
  }

  static of(value) {
    return new Writer(value, '');
  }

  map(fn) {
    const result = fn(this.value);
    return new Writer(result.value, this.log   result.log);
  }

  flatMap(fn) {
    const result = fn(this.value);
    return new Writer(result.value, this.log   result.log);
  }

  tell(log) {
    return new Writer(this.value, this.log   log);
  }
}

// Usage
const writer = Writer.of(3)
  .map(value => new Writer(value   1, 'Incremented\n'))
  .flatMap(value => new Writer(value * 2, 'Doubled\n'));

console.log(writer); 
// Writer { value: 8, log: 'Incremented\nDoubled\n' }

7. Mónada estatal

La mónada de estado se utiliza para manejar cálculos que mantienen el estado.

Implementación
class State {
  constructor(runState) {
    this.runState = runState;
  }

  static of(value) {
    return new State(state => [value, state]);
  }

  map(fn) {
    return new State(state => {
      const [value, newState] = this.runState(state);
      return [fn(value), newState];
    });
  }

  flatMap(fn) {
    return new State(state => {
      const [value, newState] = this.runState(state);
      return fn(value).runState(newState);
    });
  }

  run(initialState) {
    return this.runState(initialState);
  }
}

// Usage
const increment = new State(state => [state   1, state   1]);

const result = increment
  .flatMap(() => increment)
  .flatMap(() => increment)
  .run(0);

console.log(result); // [3, 3]

Conclusión

Las mónadas proporcionan una forma estructurada y predecible de manejar cálculos y transformaciones de datos en programación funcional. Cada tipo de mónada tiene un propósito específico, desde manejar valores opcionales con Maybe Monad hasta administrar operaciones asincrónicas con Promise Monad.

Declaración de liberación Este artículo se reproduce en: https://dev.to/francescoagati/introduction-to-functional-programming-in-javascript- Different-monads-11-2je1?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