[訳]関数式JavaScriptのFunnctors


Functor
まず次のコードを見てください.
function plus1(value) {  
    return value + 1;
}
これは一つの一般関数であり、一つのintegerをパラメータとして受信し、もう1を加えて返します.同様に、2を追加する関数もあります.後でこれらの関数を使います.
function plus2(value) {  
    return value + 2;
}
下記の組合せ関数を書いて、必要に応じて上記の関数を実行します.
function F(value, fn) {  
    return fn(value);
}

F(1, plus1) ==>> 2
正しいintegerパラメータが入ったとき、この合成関数Fは正常に動作しています.もし入ってきたデータタイプがArrayだったら?
F([1, 2, 3], plus1)   ==>> '1,2,31'
私たちはArray of integersをあげました.彼女たちとplus1の数値を加算してもらいたいです.結果はstringです.結果は違っています.私たちはArrayで始めました.結果はstringに戻りました.タイプも合っていません.言い換えれば、私たちのこのプログラムは入力の構造をバラバラにしました.私たちはやはり関数Fが「正しいこと」をしてほしいです.入力パラメータのデータ構造を維持し、各handlerによって正しく処理させます.
OKです.ここで言っている「入力パラメータのデータ構造を維持する」とは?この関数Fは、入ってきたArrayを分解し、それぞれの値を得るべきである.handlerに順次渡します.その後、handlerの処理後の各結果を新たなArrayにカプセル化し、この新しいArrayに戻る.良いニュースは私のこのようなたわごとの言うものはすべてあなたが書く必要はないので、JavaScriptはすでにこのような関数を書きました.彼女の名前はmapです.
[1, 2, 3].map(plus1)   ==>> [2, 3, 4]
mapfunctorです.functorは1つの関数で、1つの数値、1つのhandlerを受け取って、それから仕事をします!
もう少し詳しく話してくださいfunctorは一つの関数であり、一つの数値、一つのhandlerを受信し、入ってきた元の値を分解し、それぞれの分解値を得て、handlerを呼び出して、前のステップのデータを順次処理し、処理後の複数のデータを新たな構造体に再パッケージし、最後にこの新しい構造体に戻る.
ここでは、着信値の種類に注意してください.分解した各数値は元のデータタイプでもあり、集合かもしれません.
また、最後に戻ったデータのタイプも、必ずしも入ってきたデータのタイプと同じである必要はない.上記の例では、mapの入力と返却値は同じデータタイプで、全部Arrayです.戻ってきたデータ構造は任意の構造であってもよく、それぞれの数値を取得すれば良い.したがって、Arrayをパラメータとして受信する関数があると仮定するが、keysを含むObjectを返し、各keyは対応する数値を指す.これもfunctorである.JavaScriptでは、filterfunctorです.彼女は相変わらずArrayに戻りますが、forEachは違います.彼女はundefinedに戻ります.これは、forEachには「入力パラメータを維持するデータ構造」がないということです.Functorsは数学で「homomomorphiss between categories」という概念については分かりませんが、大丈夫です.それぞれ単語を変えて読みます.
  • homo=いくつか、複数
  • morphisms=データ構造を維持する関数
  • category=タイプ
  • 上記の語彙解析によれば、関数Fは、2つの一般関数fgの組み合わせとして見なされてもよい.
    F(f . g) = F(f) . F(g)
    .は、組み合わせを表している.すなわち、functorsは、合成特性を保存しなければならない.
    この方程式に基づいて、関数がfunctorかどうかの結論を出すことができます.
    アラy Functor
    先ほど私達はmapを見ましたが、Arrayfunctorです.次にArray.mapfunctorであることを証明します.
    function compose(f, g) {
        return function(x) {
            return f(g(x));
        };
    }
    複数の関数を組み合わせると、前の関数の実行結果を次の関数に渡すことで、複数の関数を順次呼び出します.上記のcomposeは右から左に実行され、gの実行結果をfに伝えます.
    [1, 2, 3].map(compose(plus1, plus2))   ==>> [ 4, 5, 6 ]
    
    [1, 2, 3].map(plus2).map(plus1)        ==>> [ 4, 5, 6 ]
    見てくださいあなたがどう書くかによって、結果は同じです.したがって、mapfunctorです.
    他のfunctorsを試してみます.functorsによってもたらされるパラメータのタイプは、任意のタイプであってもよく、彼女の値を分解して、新しいデータ構造に戻る方法があるならば.
    String Functor
    OKです.stringを処理できるfunctorを書いてもいいですか?
    まず問題を書きます.一つのstringを分解してもいいですか?必要ですよ.もし一つのstringを一つのArray of charsとしたら、分解してもいいですか?だから、問題はあなたがどう考えているかにあります.
    そして、charの各々が実はintegerchar codeを持っていることも知っています.私は上のplus1を使って各charを操作して、全結果をstringにカプセル化してから戻ります.
    function stringFunctor(value, fn) {  
        var chars = value.split('');
        return chars.map(function(char) {  
            return String.fromCharCode(fn(char.charCodeAt(0)));
        }).join('');
    }
    
    stringFunctor("ABCD", plus1) ==>> "BCDE"
    牛の強いところを感じ始めましたか?あなたはstring functorに基づいてXXの解像度を書くことができます.
    Function FuntorJavaScriptでは、関数は一等公民である.関数は他のどのタイプのようにも使えるという意味です.ですから、関数にサービスするfunctorを書いてもいいですか?
    答えは肯定です.
    どのように一つの関数を分解するかは問題です.簡単にしてください.この関数を直接実行して、彼女の戻り値を使います.でも、馬鹿もこれが問題があると知っています.(実行にはパラメータが必要です.)ここでは、私たちは必ず入ってきた関数そのものを、その入ってきた「値」として認識します.これを明確にしました.もう一つの関数を返したら、functorに見えますよね?この返却された関数が実行されると、指定されたパラメータが入力されます.実は、彼女の内部には入ってきたパラメータをvalue関数に渡し、value(initial)の結果をfnに伝え、最後に最終的な戻り値になります.
    function functionFunctor(value, fn) {
        return function(initial) {
            return function() {
                return fn(value(initial));
            };
        };
    }
    
    var init = functionFunctor(function(x) {return x * x}, plus1);
    var final = init(2);
    final() ==> 5
    はっきり言って、このFunction functorは特別なことをしていません.ただし、最終的にfunctorを実行しないと、何も起こらないので注意してください.すべてのものは一時的に保存されます.最終的に実行されるまではfunctor.Function functorによって、他の関数的プログラムの内容が派生されてもよく、例えば、状態メンテナンス、連続呼び出し、またはPromise.興味があったら、自分で勉強した知識に基づいてこのいくつかの概念を実現してみてもいいです.
    MayBe Functor
    function mayBe(value, fn) {
        return value === null || value === undefined ? value : fn(value);
    }
    これも合法的なfunctorです.
    mayBe(undefined, compose(plus1, plus2))     ==>> undefined
    mayBe(mayBe(undefined, plus2), plus1)       ==>> undefined
    mayBe(1, compose(plus1, plus2))             ==>> 4
    mayBe(mayBe(1, plus2), plus1)               ==>> 4
    mayBeは上のテストに合格しました.ここは本当に分解と再包装がありません.伝わるのが空なら、引き返すのも空です.mayBeは、簡単で効果的な経路選択関数であり、以下のような表記と同じである.
    if (result === null) {
        return null;
    } else {
        doSomething(result);
    }
    Identity Function
    function id(x) {
        return x;
    }
    上のこれはいわゆるidentity functionです.彼女は入ってきたパラメータをもう一度返しました.彼女はこのように呼んでいます.私も仕方がないです.数学計算では、コンビネーション関数のIDを表しています.
    前に私たちはfunctorを勉強しました.つまり、グループの特性を保存します.実はfunctorも彼女のidentityを保存しなければなりません.
    F(value, id) = value
    mapを取ってみます.
    [1, 2, 3].map(id)    ==>>  [ 1, 2, 3 ]
    Type SignatureType Signatureは、関数のパラメータおよび返却値の形態を表している.その前に私たちが書いたplus1の関数のType Signatureは次の通りです.
    f: int -> int
    mapfunctorとして、Type SignaturehandlerType Signatureに依存している.例えば、mapplus1を組み合わせて使うと、彼女のType Signatureは次のようになります.
    map: [int] -> [int]
    ただし、handlerType Signatureは前後一致する必要がないので、以下のようにする.
    f: int -> string
    mapType Signatureもいいです.
    map: [int] -> [string]
    すなわち、タイプの変化は、functorの関数合成特性に影響を与えない.一般に、functorType Signatureは、このように定義されてもよい.
    F: A -> B
    たとえば、mapは数値配列に入ることができますが、文字列配列を返します.彼女は相変わらずfunctorです.Monadsは特別なタイプのfunctorであり、以下のように定義されている.
    M: A -> A
    詳細は次回をご覧ください.
    原文の住所:Funtional JavaScript-functors