Rumah  >  Artikel  >  hujung hadapan web  >  Pengenalan kepada Pengaturcaraan Fungsian dalam JavaScript: Monad yang berbeza #11

Pengenalan kepada Pengaturcaraan Fungsian dalam JavaScript: Monad yang berbeza #11

王林
王林asal
2024-07-18 20:34:41945semak imbas

Introduction to Functional Programming in JavaScript: Different monads #11

Monad ialah konsep asas dalam pengaturcaraan berfungsi yang menyediakan cara untuk mengendalikan pengiraan dan transformasi data secara berstruktur. Terdapat pelbagai jenis monad, setiap satu direka untuk menyelesaikan masalah tertentu dan mengendalikan pelbagai jenis data dan kesan.

Apa itu Monad?

Monad ialah abstraksi yang membenarkan rantaian operasi pada nilai yang dibalut. Ia ditakrifkan oleh tiga sifat utama:

  1. Unit (juga dipanggil daripada atau kembali): Fungsi yang mengambil nilai dan membungkusnya dalam monad.
  2. Bind (juga dipanggil flatMap atau chain): Fungsi yang mengambil nilai monad dan fungsi yang mengembalikan monad, menggunakan fungsi itu pada nilai yang dibalut dan mengembalikan monad baharu.
  3. Associativity: Komposisi operasi monadik hendaklah bersekutu.

Jenis Monad Biasa

  1. Mungkin Monad
  2. Sama ada Monad
  3. Janji Monad
  4. Senaraikan Monad
  5. Monad Pembaca
  6. Penulis Monad
  7. Monad Negeri

1. Mungkin Monad

Mungkin Monad digunakan untuk mengendalikan nilai pilihan. Ia mewakili pengiraan yang mungkin gagal atau mengembalikan batal atau tidak ditentukan.

Perlaksanaan
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. Sama ada Monad

Either Monad digunakan untuk mengendalikan pengiraan yang boleh mengembalikan sama ada nilai kejayaan (Kanan) atau nilai ralat (Kiri).

Perlaksanaan
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. Janji Monad

Monad Janji digunakan untuk mengendalikan pengiraan tak segerak.

Penggunaan
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. Senaraikan Monad

Senarai Monad digunakan untuk mengendalikan pengiraan yang menghasilkan senarai nilai.

Perlaksanaan
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. Pembaca Monad

Monad Pembaca digunakan untuk mengendalikan pengiraan yang bergantung pada beberapa persekitaran atau konfigurasi yang dikongsi.

Perlaksanaan
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. Penulis Monad

Monad Penulis digunakan untuk mengendalikan pengiraan yang menghasilkan nilai bersama log atau data tambahan.

Perlaksanaan
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. Monad Negeri

Monad Negeri digunakan untuk mengendalikan pengiraan yang mengekalkan keadaan.

Perlaksanaan
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]

Kesimpulan

Monad menyediakan cara berstruktur dan boleh diramal untuk mengendalikan pengiraan dan transformasi data dalam pengaturcaraan berfungsi. Setiap jenis monad mempunyai tujuan tertentu, daripada mengendalikan nilai pilihan dengan Maybe Monad kepada menguruskan operasi tak segerak dengan Promise Monad.

Atas ialah kandungan terperinci Pengenalan kepada Pengaturcaraan Fungsian dalam JavaScript: Monad yang berbeza #11. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn