"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Introduction à la programmation fonctionnelle en JavaScript : Différentes monades #11

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

Publié le 2024-07-29
Parcourir:593

Introduction to Functional Programming in JavaScript: Different monads #11

Les monades sont un concept fondamental de la programmation fonctionnelle qui fournit un moyen 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 encapsulé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 chaîne) : 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. Monade de promesse
  4. Liste des monades
  5. Monade de lecteur
  6. Monade d'écrivain
  7. Monade d'État

1. Peut-être Monade

La monade Maybe est utilisée pour gérer les valeurs facultatives. Il représente un calcul qui peut échouer ou renvoyer null ou undefined.

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

Soit Monade 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 dans la 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.

Déclaration de sortie Cet article est reproduit sur : https://dev.to/francescoagati/introduction-to-functional-programming-in-javascript-différent-monads-11-2je1?1 En cas de violation, veuillez contacter [email protected] pour le supprimer
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3