Mônadas são um conceito fundamental em programação funcional que fornece uma maneira de lidar com cálculos e transformações de dados de maneira estruturada. Existem vários tipos de mônadas, cada uma projetada para resolver problemas específicos e lidar com diferentes tipos de dados e efeitos.
Uma mônada é uma abstração que permite o encadeamento de operações em valores agrupados. É definido por três propriedades principais:
O Maybe Monad é usado para lidar com valores opcionais. Representa um cálculo que pode falhar ou retornar nulo ou 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' }
O Both Monad é usado para lidar com cálculos que podem retornar um valor de sucesso (Direita) ou um valor de erro (Esquerda).
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 }
O Promise Monad é usado para lidar com cálculos assíncronos.
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); });
A List Monad é usada para lidar com cálculos que produzem uma 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 ] }
O Reader Monad é usado para lidar com cálculos que dependem de algum ambiente ou configuração compartilhada.
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' }
O Writer Monad é usado para lidar com cálculos que produzem um valor junto com um log ou dados adicionais.
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' }
O State Monad é usado para lidar com cálculos que mantêm o 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]
Mônadas fornecem uma maneira estruturada e previsível de lidar com cálculos e transformações de dados em programação funcional. Cada tipo de mônada serve a um propósito específico, desde o tratamento de valores opcionais com o Maybe Monad até o gerenciamento de operações assíncronas com o Promise Monad.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3