.map()は、関数fを値xに適用します//配列のコンテキスト内。[40]この場合、Arrayはコンテキストであり、xはマッピングする値です。この例には配列の配列は含まれていませんが、.concat()を使用してJSで配列をフラット化できます。[1、2、3、4]おそらくすでにモナドを使用しているでしょう。スキルレベルやカテゴリ理論の理解に関係なく、モナドを使用するとコードの操作が簡単になります。モナドを利用しないと、コードの操作が難しくなる場合があります(たとえば、コールバック地獄、ネストされた条件分岐、より冗長)。ソフトウェア開発の本質は作曲であり、モナドは作曲を容易にすることを忘れないでください。モナドとは何かの本質をもう一度見てみましょう。bの関数を作成できます。Functor(b)。F(b)を構成できます。F(b)を構成できます。これらはすべて、関数構成を表現する単なる異なる方法です。関数が存在する理由は、それらを構成できるためです。関数を使用すると、複雑な問題を簡単に分離して簡単に解決できるため、さまざまな方法で構成してアプリケーションを作成できます。関数とその適切な使用を理解するための鍵は、関数の構成をより深く理解することです。関数構成は、データが通過する関数パイプラインを作成します。パイプラインの最初の段階で入力を行い、パイプラインの最後の段階からいくつかのデータをポップし、変換します。それが機能するためには、パイプラインの各ステージは、前のステージが返すデータ型を予期している必要があります。タイプはすべて簡単に整列するため、単純な関数の作成は簡単です。出力タイプbと入力タイプbを一致させるだけで、ビジネスを開始できます。F(b)をマッピングしている場合、型が並んでいるので、ファンクターを使った作成も簡単です。F(c)などから関数を作成する場合は、モナドが必要です。それを明確にするために、F()をM()に交換しましょう。fの入力には、タイプbが必要でしたが、得られたのはタイプM(b)(bのモナド)でした。その不整合のため、composeM()は、gが返すM(b)をアンラップして、fに渡すことができるようにする必要があります。fは、タイプM(b)ではなくタイプbを想定しているためです。このプロセス(多くの場合、.bind()または.chain()と呼ばれます)は、フラット化とマップが行われる場所です。次の関数に渡す前に、M(b)からbをアンラップします。M(b)のために型を揃えて、それらを構成できるようにします。M(c)からのチェーン内で発生します。チェーンの呼び出しはcomposeM()内で処理されます。高いレベルでは、心配する必要はありません。通常の関数の作成に使用するのと同じ種類のAPIを使用して、モナドを返す関数を作成するだけです。bからの単純なマッピングではないため、モナドが必要です。一部の関数では、副作用(約束、ストリーム)の処理、分岐の処理(たぶん)、例外の処理(どちらか)などが必要です。具体的な例を次に示します。Promise(Boolean)問題を実証するためにいくつかの関数を書きましょう。//それらを作成してみてください。警告:これは失敗します。authUser(3).then(trace(label));}hasPermission()をgetUserById()で作成してauthUser()を作成しようとすると、hasPermission()がUserオブジェクトを予期し、代わりにPromise(User)を取得するため、大きな問題が発生します。これを修正するには、compose()をcomposePromises()に置き換える必要があります。これは、.then()を使用して関数の合成を行う必要があることを認識しているcomposeの特別なバージョンです。true}composeM()の動作については後で説明します。Monad(b)この場合、モナドは本当にプロミスなので、これらのプロミスを返す関数を構成するとき、hasPermission()が期待しているUserの代わりにPromise(User)があります。Monad(b)が残ることに注意してください。これは通常のファンクター.map()です。xを平坦化できるものがあれば、ビジネスになります。aまた、モナドはファンクターでもあるため、次のようにマッピングすることもできます。M(b)mapとflattenを組み合わせると、チェーンが得られます。これは、ハインリッヒクライスリにちなんで名付けられたモナドリフティング関数の関数合成(別名Kleisli合成)です。M(b)モナドの場合、.map()メソッドは多くの場合パブリックAPIから省略されます。flattenは.map()を明確に記述しませんが、それを作成するために必要なすべての要素があります。flatMap)を持ち上げることができる場合、.map()を作成できます。}});したがって、モナドに対して.of()および.chain()/。join()を定義すると、.map()の定義を推測できます。constructorおよび/またはconstructor.of()メソッドです。カテゴリー理論では、「ユニット」と呼ばれます。それは、型をモナドのコンテキストに持ち上げるだけです。aをaのモナドに変換します。Haskellでは、(非常に紛らわしいことに)returnと呼ばれます。ほとんどの人が関数returnと混同するため、大声で話そうとすると非常に混乱します。lift」、コードでは.of()と呼びます。その平坦化プロセス(.chain()のマップなし)は、通常flatten()またはjoin()と呼ばれます。join()は.chain()/。flatMap()に組み込まれているため、完全に省略されます。フラット化はコンポジションに関連付けられることが多いため、マッピングと頻繁に組み合わされます。M(a)関数を構成するには、アンラップ+マップの両方が必要であることを忘れないでください。扱うモナドの種類によっては、展開プロセスは非常に簡単です。アイデンティティモナドの場合、結果の値をモナドコンテキストに戻さないことを除いて、.map()と同じです。これには、1層のラッピングを破棄する効果があります。{value})`});//このモナドの型リフトはただ//ファクトリへの参照。Oの待機などの奇妙なものが通常隠れている場所でもあります。すべてのソフトウェア開発において、作曲は、本当に興味深いすべてのことが起こる場所です。promiseでは、.chain()は.then()と呼ばれます。promise.then(f)を呼び出しても、f()はすぐには呼び出されません。代わりに、Promiseが解決するのを待ってから、f()を呼び出します(そのため名前が付けられます)。);}promiseでは、.chain()の代わりに.then()が使用されますが、ほぼ同じです。約束は厳密にはモナドではないことを聞いたことがあるかもしれません。それは、値がそもそも約束である場合にのみ外側の約束を解くからです。それ以外の場合、.then()は.map()のように動作します。promise値と他の値では動作が異なるため、.then()は、すべてのファンクターやモナドがすべての与えられた値を満たす必要のあるすべての数学的な法則を厳密には守りません。実際には、その動作の分岐を認識している限り、通常はどちらかとして扱うことができます。いくつかの一般的な構成ツールは、promiseでは期待どおりに動作しない可能性があることに注意してください。約束を持ち上げる関数を作成するために使用したcomposeM関数を詳しく見てみましょう。g(x)[method](f)));その奇妙なレデューサーに隠されているのは、関数合成の代数的定義です:f(g(x))。.map()が関数構成を達成することの証明。mapへの呼び出しの連鎖は関数合成です。g(x).map(f)));これは、標準f(g(x))のわずかな再定式化です。Functor(b)の任意の数の関数を指定すると、各関数を反復処理し、各関数をその入力値xに適用します。.reduce()メソッドは、2つの入力値を持つ関数を取ります。アキュムレーター(この場合はf)、および配列内の現在の項目(g)です。g(x).map(f)を返します。g(x).map(f)がcompose(f、g)(x)をファンクターのコンテキストに持ち上げることと同等であることをすでに証明しました。コンテナ内の値にf(g(x))を適用することと同じです。この場合、配列内の値に構成を適用します。パフォーマンスの警告:アレイにはこれをお勧めしません。この方法で関数を構成するには、配列全体(数十万のアイテムを含む可能性がある)で複数回の反復が必要です。b関数を最初に作成し、次に配列上に1回マッピングするか、.reduce()またはトランスデューサーで反復を最適化します。配列データを介した同期的な熱心な関数アプリケーションの場合、これは過剰です。多くのことは非同期または遅延であり、多くの関数は、例外や空の値の分岐などの厄介なものを処理する必要があります。そこでモナドが登場します。モナドは、コンポジションチェーン内の以前の非同期または分岐アクションに依存する値に依存できます。これらの場合、単純な関数構成に対して単純な値を取得することはできません。Monad(b)の形式を取ります。データを受け取り、APIをヒットし、対応する値を返す関数と、そのデータを受け取り、別のAPIをヒットし、そのデータの計算結果を返す別の関数があるときはいつでも、関数を作成する必要があります。API呼び出しは非同期であるため、戻り値をpromiseやobservableのようなものでラップする必要があります。Monad(c)です。cの関数の構成は、タイプが揃っているため簡単です。f(g(a))ではありませんfはMonad(b)ではなくbを期待しているためです。具体的に見て、それぞれが約束を返す非同期関数のペアを作成しましょう。//構成の約束:42}結果が正しく記録されるようにcomposePromises()を記述する方法は?ヒント:すでに見ました。composeMap()関数を覚えていますか?必要なことは、.map()呼び出しを.then()に変更することだけです。Promise.then()は基本的に非同期の.map()です。//構成の約束:42}奇妙な部分は、2番目の関数f(gの後のfを思い出してください)を押すと、入力値が約束であることです。b型ではなく、Promise(b)型ですが、fはラップされていないb型を取ります。bから展開するプロセスがあります。その操作は、結合またはフラット化と呼ばれます。composeMap()とcomposePromises()がほぼ同一の関数であることに気づいたかもしれません。これは、両方を処理できる高階関数の完璧なユースケースです。chainメソッドをカリー化された関数に混ぜて、角括弧表記を使用してみましょう。g(x)[method](f)));これで、次のような特殊な実装を作成できます。独自のモナドの構築を開始する前に、すべてのモナドが満たすべき3つの法則があることを知っておく必要があります。f(x).chain(g))アイデンティティ法モナドはファンクターです。射は矢印で表されます。オブジェクト間に明示的に表示される矢印に加えて、カテゴリ内の各オブジェクトには、それ自体に戻る矢印もあります。この矢印は、アイデンティティ矢印と呼ばれ、通常、オブジェクトを指し、同じオブジェクトにループバックする小さな円形の矢印として描画されます。連想性とは、作曲時に括弧をどこに置くかが問題ではないことを意味します。