Maison  >  Article  >  interface Web  >  Introduction à la programmation fonctionnelle en JavaScript : Différentes monades #11

Introduction à la programmation fonctionnelle en JavaScript : Différentes monades #11

王林
王林original
2024-07-18 20:34:41945parcourir

Introduction to Functional Programming in JavaScript: Different monads #11

Les monades sont un concept fondamental de la programmation fonctionnelle qui permet de gérer les calculs et les transformations de données de manière structurée. Il existe différents types de monades, chacune conçue pour résoudre des problèmes spécifiques et gérer différents types de données et d'effets.

Qu'est-ce qu'une Monade ?

Une monade est une abstraction qui permet d'enchaîner des opérations sur des valeurs enveloppées. Il est défini par trois propriétés principales :

  1. Unité (également appelée of ou return) : Une fonction qui prend une valeur et l'enveloppe dans une monade.
  2. Bind (également appelé flatMap ou chain) : une fonction qui prend une valeur monadique et une fonction qui renvoie une monade, applique la fonction à la valeur encapsulée et renvoie une nouvelle monade.
  3. Associativité : La composition des opérations monadiques doit être associative.

Types courants de monades

  1. Peut-être Monade
  2. Soit Monade
  3. Promesse Monade
  4. Liste des monades
  5. Monade de lecture
  6. Monade d'écrivain
  7. Monade d'État

1. Peut-être Monade

La Maybe Monad est utilisée pour gérer les valeurs facultatives. Il représente un calcul qui pourrait échouer ou renvoyer null ou indéfini.

Mise en œuvre
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. Soit Monade

La Monade Soit est utilisée pour gérer des calculs qui peuvent renvoyer soit une valeur de réussite (à droite), soit une valeur d'erreur (à gauche).

Mise en œuvre
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. Promesse Monade

La Promise Monad est utilisée pour gérer les calculs asynchrones.

Usage
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. Liste des monades

La List Monad est utilisée pour gérer les calculs qui produisent une liste de valeurs.

Mise en œuvre
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. Lecteur Monade

Le Reader Monad est utilisé pour gérer les calculs qui dépendent d'un environnement ou d'une configuration partagés.

Mise en œuvre
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. Monade de l'écrivain

Le Writer Monad est utilisé pour gérer des calculs qui produisent une valeur avec un journal ou des données supplémentaires.

Mise en œuvre
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. Monade d'État

La Monade d'État est utilisée pour gérer les calculs qui maintiennent l'état.

Mise en œuvre
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]

Conclusion

Les monades offrent un moyen structuré et prévisible de gérer les calculs et les transformations de données en programmation fonctionnelle. Chaque type de monade répond à un objectif spécifique, de la gestion des valeurs facultatives avec Maybe Monad à la gestion des opérations asynchrones avec Promise Monad.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn