"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Introdução à Programação Funcional em JavaScript: Diferentes mônadas #11

Introdução à Programação Funcional em JavaScript: Diferentes mônadas #11

Publicado em 2024-07-29
Navegar:974

Introduction to Functional Programming in JavaScript: Different monads #11

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.

O que é uma mônada?

Uma mônada é uma abstração que permite o encadeamento de operações em valores agrupados. É definido por três propriedades principais:

  1. Unidade (também chamada de ou retorno): Uma função que pega um valor e o envolve em uma mônada.
  2. Bind (também chamado de flatMap ou chain): Uma função que recebe um valor monádico e uma função que retorna uma mônada, aplica a função ao valor agrupado e retorna uma nova mônada.
  3. Associatividade: A composição das operações monádicas deve ser associativa.

Tipos comuns de mônadas

  1. Talvez Mônada
  2. Qualquer mônada
  3. Mônada da promessa
  4. Listar Mônada
  5. Leitor Mônada
  6. Escritor Mônada
  7. Mônada Estadual

1. Talvez Mônada

O Maybe Monad é usado para lidar com valores opcionais. Representa um cálculo que pode falhar ou retornar nulo ou indefinido.

Implementação
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. Qualquer mônada

O Both Monad é usado para lidar com cálculos que podem retornar um valor de sucesso (Direita) ou um valor de erro (Esquerda).

Implementação
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. Mônada da promessa

O Promise Monad é usado para lidar com cálculos assíncronos.

Uso
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. Listar Mônada

A List Monad é usada para lidar com cálculos que produzem uma lista de valores.

Implementação
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. Leitor Mônada

O Reader Monad é usado para lidar com cálculos que dependem de algum ambiente ou configuração compartilhada.

Implementação
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. Escritor Mônada

O Writer Monad é usado para lidar com cálculos que produzem um valor junto com um log ou dados adicionais.

Implementação
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. Mônada Estadual

O State Monad é usado para lidar com cálculos que mantêm o estado.

Implementação
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]

Conclusão

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.

Declaração de lançamento Este artigo está reproduzido em: https://dev.to/francescoagati/introduction-to-funcional-programming-in-javascript- Different-monads-11-2je1?1 Se houver alguma violação, entre em contato com [email protected] para excluí-lo
Tutorial mais recente Mais>

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