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.
Una mónada es una abstracción que permite el encadenamiento de operaciones sobre valores ajustados. Se define por tres propiedades principales:
Maybe Monad se utiliza para manejar valores opcionales. Representa un cálculo que podría fallar o devolver un valor nulo o indefinido.
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' }
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).
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 }
Promise Monad se utiliza para manejar cálculos asincrónicos.
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); });
La mónada de lista se utiliza para manejar cálculos que producen una lista de valores.
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 ] }
Reader Monad se utiliza para manejar cálculos que dependen de algún entorno o configuración compartido.
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' }
Writer Monad se utiliza para manejar cálculos que producen un valor junto con un registro o datos adicionales.
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' }
La mónada de estado se utiliza para manejar cálculos que mantienen el estado.
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]
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.
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