ここにも同様の質問がありますが、それらは特定のプログラミング言語に関連付けられており、概念レベルでの回答を探しています。
私が理解しているように、ファンクターは本質的に不変のコンテナーであり、別のファンクターを派生させるmap() APIを公開します。特定のファンクターをモナドと呼ぶことを可能にする追加はどれですか?
私が理解しているように、すべてのモナドはファンクターですが、すべてのファンクターがモナドであるとは限りません。
(これは圏論の概念の簡単な説明になることに注意してください)
ファンクターは、値のセットaから別の値のセットへの関数です:_a -> b
_。プログラミング言語の場合、これは_String -> Integer
_から始まる関数である可能性があります。
function fn(text: string) : integer
合成とは、ある関数の値を次の関数の値への入力として使用する場合です:fa(fb(x))
。例えば:
hash(lowercase(text))
モナドを使用すると、他の方法では構成できないファンクターを作成するか、コンポジションに機能を追加してファンクターを作成するか、またはその両方を行うことができます。
最初の例は、ファンクターのモナドString -> (String, Integer)
です。
2番目の例は、値に対して呼び出された関数の数をカウントするモナドです。
モナドには、必要な機能に加えて他の2つの機能を担当するFunctor T
が含まれています。
input -> T(input)
T(T(input)) -> T(input)
最初の関数を使用すると、入力値をモナドが作成できる値のセットに変換できます。 2番目の機能は構成を可能にします。
したがって、結論として、すべてのモナドはファンクターではありませんが、ファンクターを使用してその目的を完了します。
圏論に入らずに私の理解を説明させてください、
ファンクターとモナドはどちらも、ラップされた出力を返すラップされた入力にtoolを提供します。
ファンクター=ユニット+マップ(ツール)
ここで、unit =生の入力を受け取り、それを小さなコンテキスト内にラップするものです。
map =関数を入力として受け取り、それをラッパーの生の値に適用して、ラップされた結果を返すツールです。
例:整数を2倍にする関数を定義しましょう// doubleMe :: Int a-> Int b const doubleMe = a => 2 * a; Maybe(2).map(doubleMe)// Maybe(4)
モナド=ユニット+フラットマップ(またはバインドまたはチェーン)
flatMap =名前がこぼれたときにマップを平坦化するツールです。以下の例ですぐに明らかになります。
例:両方が空白でない場合にのみ2つの文字列を追加するカリー化関数があるとします。
以下のように定義させてください。
append::( string a、string b)->たぶん(string c)
Map(ツールはFunctorに付属)の問題を見てみましょう。
Maybe( "a")。map(append( "b"))// Maybe(Maybe( "ab"))
どうしてここに2つあるの?
まあ、それはマップが行うことです、それはラップされた値に提供された関数を適用し、結果をラップします。
これをいくつかのステップに分けてみましょう。
ステップ1:マップされた関数をラップされた値に適用するここで、マップされた関数はappend( "b")であり、ラップされた値は "a"であり、結果はMaybe( "ab")
step2:Maybe(Maybe( "ab"))を返す結果をラップします。
これで、関心のある値が2回ラップされます。救助するflatMapがここにあります。
Maybe( "a")。flatMap(append( "b"))// Maybe( "ab")
もちろん、ファンクターとモナドは他のいくつかの法律にも従わなければなりませんが、これは求められている範囲内ではないと思います。