「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > JavaScript の関数型プログラミングの概要: モナドを実行する #12

JavaScript の関数型プログラミングの概要: モナドを実行する #12

2024 年 8 月 25 日に公開
ブラウズ:816

Introduction to Functional Programming in JavaScript: Do monads #12

関数型プログラミングでは、モナドは構造化された予測可能な方法で計算を処理する方法を提供します。さまざまなモナドの中でも、Do モナド (「Do 記法」または「モナド内包表記」とも呼ばれます) は、モナド演算をより読みやすく命令型スタイルで処理できる強力な構造です。

Do モナドとは何ですか?

Do モナドは、命令型プログラミングに似たスタイルでモナド演算のシーケンスを記述できるようにすることで、モナドの操作を簡素化する糖衣構文です。 .then や . flatMap で操作を連鎖させる代わりに、Do Monad を使用すると、より単純で読みやすいコードを作成できます。

Do モナドの利点

  1. 可読性: 複雑なモナド演算をクリーンで線形な方法で書くことができます。
  2. 命令型スタイル: 命令型プログラミングに慣れている人になじみのあるスタイルでモナド計算を表現する方法を提供します。
  3. エラー処理: 明確で一貫した構造を提供することにより、モナド演算におけるエラーの処理を簡素化します。

JavaScript での Do モナドの実装

JavaScript には Haskell のような Do モナドのサポートが組み込まれていませんが、ジェネレーター関数とカスタム ランナーを使用して同様の構造を実装できます。

例: Do Monad ランナーの実装

Promise モナドを処理できる Do Monad ランナーを実装することから始めましょう。

function* doGenerator() {
  const a = yield Promise.resolve(1);
  const b = yield Promise.resolve(2);
  const c = yield Promise.resolve(a   b);
  return c;
}

function runDo(genFunc) {
  const iter = genFunc();

  function handle(result) {
    if (result.done) return Promise.resolve(result.value);
    return Promise.resolve(result.value).then(res => handle(iter.next(res)));
  }

  return handle(iter.next());
}

// Usage
runDo(doGenerator).then(result => console.log(result)); // 3

この例では、doGenerator は Promise を生成するジェネレーター関数です。 runDo 関数はジェネレーターを実行し、生成された各 Promise を処理し、解決された値をジェネレーターに返します。

Do モナドの実践的な応用

Do モナドは、モナド演算を読みやすく保守しやすい方法で順序付けする必要があるさまざまなシナリオで使用できます。

例: 非同期操作の処理

より複雑な非同期操作を処理できるように前の例を拡張しましょう。

function* fetchUserData() {
  const user = yield fetch('https://api.example.com/user/1').then(res => res.json());
  const posts = yield fetch(`https://api.example.com/user/${user.id}/posts`).then(res => res.json());
  const firstPost = posts[0];
  const comments = yield fetch(`https://api.example.com/posts/${firstPost.id}/comments`).then(res => res.json());
  return { user, firstPost, comments };
}

runDo(fetchUserData).then(result => console.log(result));

この例では、 fetchUserData は、ユーザー データ、その投稿、および最初の投稿のコメントを取得するための Promise を生成するジェネレーター関数です。 runDo 関数は、これらの非同期操作を読みやすく構造化された方法で実行します。

例:Maybe Monad を使用したオプションの値の処理

Do モナド パターンは、Maybe などの他のモナドでも使用できます。

class Maybe {
  constructor(value) {
    this.value = value;
  }

  static of(value) {
    return new Maybe(value);
  }

  map(fn) {
    return this.value === null || this.value === undefined ? Maybe.of(null) : Maybe.of(fn(this.value));
  }

  flatMap(fn) {
    return this.value === null || this.value === undefined ? Maybe.of(null) : fn(this.value);
  }
}

function* maybeDoGenerator() {
  const a = yield Maybe.of(1);
  const b = yield Maybe.of(2);
  const c = yield Maybe.of(a   b);
  return c;
}

function runMaybeDo(genFunc) {
  const iter = genFunc();

  function handle(result) {
    if (result.done) return Maybe.of(result.value);
    return result.value.flatMap(res => handle(iter.next(res)));
  }

  return handle(iter.next());
}

// Usage
const result = runMaybeDo(maybeDoGenerator);
console.log(result); // Maybe { value: 3 }

この例では、maybeDoGenerator は、Maybe モナドで動作するジェネレーター関数です。 runMaybeDo 関数はジェネレーターを実行し、生成されたそれぞれのMaybe値を処理し、ラップされていない値をジェネレーターに戻します。

Do モナドは、モナド操作のシーケンスをより読みやすく命令型スタイルで記述できるようにすることで、モナドの操作を簡素化する強力な構造です。 Do Monad ランナーを実装すると、複雑な非同期操作、オプションの値、その他のモナド計算を構造化された保守可能な方法で処理できます。

JavaScript は Do Monad 構文をネイティブにサポートしていませんが、ジェネレーター関数とカスタム ランナーを使用すると、同様の機能を実現できます。このアプローチにより、コードの可読性と保守性が向上し、関数型プログラミング スタイルでのモナド演算の操作が容易になります。

リリースステートメント この記事は次の場所に転載されています: https://dev.to/francescoagati/introduction-to-function-programming-in-javascript-do-monads-12-362a?1 侵害がある場合は、[email protected] までご連絡ください。それを削除するには
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3