Nest.JS | Monades -> IO

Jan 27 2023
La monade IO, également appelée « monade d'entrée/sortie », est un concept de programmation fonctionnelle qui permet de séparer la description d'une opération d'entrée/sortie de son exécution. En d'autres termes, cela vous permet de définir un calcul qui effectue une action d'E/S (telle que la lecture d'un fichier ou l'interaction avec une base de données) sans réellement effectuer cette action jusqu'à ce qu'elle soit invoquée explicitement.

La monade IO, également appelée « monade d'entrée/sortie », est un concept de programmation fonctionnelle qui permet de séparer la description d'une opération d'entrée/sortie de son exécution. En d'autres termes, cela vous permet de définir un calcul qui effectue une action d'E/S (telle que la lecture d'un fichier ou l'interaction avec une base de données) sans réellement effectuer cette action jusqu'à ce qu'elle soit invoquée explicitement.

La monade IO est souvent utilisée pour gérer les effets secondaires dans un langage de programmation fonctionnel, tel que JavaScript. La monade IO vous permet de décrire un calcul efficace de manière pure et composable, ce qui facilite le raisonnement et le test de votre code.

Une monade IO est généralement implémentée comme un objet qui a une seule méthode, appelée run, qui exécute l'action I/O et renvoie le résultat. La monade IO peut être utilisée pour enchaîner plusieurs opérations d'E/S et créer des calculs plus complexes.

Voici un exemple de la monade IO en JavaScript :

class IO {
  constructor(effect) {
    this.effect = effect
  }
  run() {
    return this.effect()
  }
  map(f) {
    return new IO(() => f(this.run()))
  }
  chain(f) {
    return new IO(() => f(this.run()).run())
  }
  // ...
}

import { Injectable } from '@nestjs/common';
import { IO, io } from 'fp-ts/lib/IO';

@Injectable()
export class MyService {
  public async getUsers(): IO<User[]> {
    return io.fromPromise(this.userRepository.find());
  }

  public async getUserById(id: string): IO<User> {
    return io.fromPromise(this.userRepository.findOne(id));
  }
}

Vous pouvez enchaîner plusieurs calculs à l'aide des méthodes .map(), .chain(), .ap().

const program: IO<string> = myService.getUsers()
    .map(users => users.filter(user => user.age > 18))
    .chain(users => myService.getUserById(users[0].id))
    .map(user => user.name)

  program.run()

Il est important de noter que cet exemple est basique et ne démontre pas toute la puissance de Monads dans la programmation fonctionnelle. Les monades peuvent être utilisées pour gérer divers cas comme la gestion des erreurs, l'enchaînement de plusieurs calculs et plus encore, il est préférable de comprendre le problème et les cas d'utilisation avant d'appliquer les monades.

De plus, la run()méthode doit être appelée pour exécuter la monade IO et obtenir les résultats, ceci est connu car impurecela dépend de l'état/du contexte externe, les monades IO sont utilisées pour séparer le code impur du code pur pour une meilleure organisation du code et les tests.

Liste des pièces :