Monaden sind ein grundlegendes Konzept in der funktionalen Programmierung, das eine Möglichkeit bietet, Berechnungen und Datentransformationen strukturiert abzuwickeln. Es gibt verschiedene Arten von Monaden, die jeweils darauf ausgelegt sind, spezifische Probleme zu lösen und unterschiedliche Arten von Daten und Effekten zu verarbeiten.
Eine Monade ist eine Abstraktion, die die Verkettung von Operationen an umschlossenen Werten ermöglicht. Es wird durch drei Haupteigenschaften definiert:
Die Maybe-Monade wird zur Verarbeitung optionaler Werte verwendet. Es stellt eine Berechnung dar, die möglicherweise fehlschlägt oder null oder undefiniert zurückgibt.
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' }
Die Entweder-Monade wird verwendet, um Berechnungen durchzuführen, die entweder einen Erfolgswert (rechts) oder einen Fehlerwert (links) zurückgeben können.
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 }
Die Promise Monad wird zur Abwicklung asynchroner Berechnungen verwendet.
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); });
Die Listenmonade wird verwendet, um Berechnungen durchzuführen, die eine Liste von Werten erzeugen.
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 ] }
Die Reader-Monade wird verwendet, um Berechnungen durchzuführen, die von einer gemeinsamen Umgebung oder Konfiguration abhängen.
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' }
Die Writer-Monade wird verwendet, um Berechnungen durchzuführen, die einen Wert zusammen mit einem Protokoll oder zusätzlichen Daten erzeugen.
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' }
Die Zustandsmonade wird verwendet, um Berechnungen durchzuführen, die den Zustand aufrechterhalten.
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]
Monaden bieten eine strukturierte und vorhersehbare Möglichkeit, Berechnungen und Datentransformationen in der funktionalen Programmierung durchzuführen. Jeder Monadentyp dient einem bestimmten Zweck, von der Verarbeitung optionaler Werte mit der Maybe-Monade bis zur Verwaltung asynchroner Vorgänge mit der Promise-Monade.
Das obige ist der detaillierte Inhalt vonEinführung in die funktionale Programmierung in JavaScript: Verschiedene Monaden #11. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!