[訳]関数式JavaScriptのFunnctors
7313 ワード
Functor
まず次のコードを見てください.
OKです.ここで言っている「入力パラメータのデータ構造を維持する」とは?この関数
もう少し詳しく話してください
ここでは、着信値の種類に注意してください.分解した各数値は元のデータタイプでもあり、集合かもしれません.
また、最後に戻ったデータのタイプも、必ずしも入ってきたデータのタイプと同じである必要はない.上記の例では、 homo=いくつか、複数 morphisms=データ構造を維持する関数 category=タイプ 上記の語彙解析によれば、関数
この方程式に基づいて、関数が
アラy Functor
先ほど私達は
他の
String Functor
OKです.
まず問題を書きます.一つの
そして、
Function Funtor
答えは肯定です.
どのように一つの関数を分解するかは問題です.簡単にしてください.この関数を直接実行して、彼女の戻り値を使います.でも、馬鹿もこれが問題があると知っています.(実行にはパラメータが必要です.)ここでは、私たちは必ず入ってきた関数そのものを、その入ってきた「値」として認識します.これを明確にしました.もう一つの関数を返したら、
MayBe Functor
前に私たちは
原文の住所:Funtional JavaScript-functors
まず次のコードを見てください.
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]
map
はfunctor
です.functor
は1つの関数で、1つの数値、1つのhandler
を受け取って、それから仕事をします!もう少し詳しく話してください
functor
は一つの関数であり、一つの数値、一つのhandler
を受信し、入ってきた元の値を分解し、それぞれの分解値を得て、handler
を呼び出して、前のステップのデータを順次処理し、処理後の複数のデータを新たな構造体に再パッケージし、最後にこの新しい構造体に戻る.ここでは、着信値の種類に注意してください.分解した各数値は元のデータタイプでもあり、集合かもしれません.
また、最後に戻ったデータのタイプも、必ずしも入ってきたデータのタイプと同じである必要はない.上記の例では、
map
の入力と返却値は同じデータタイプで、全部Array
です.戻ってきたデータ構造は任意の構造であってもよく、それぞれの数値を取得すれば良い.したがって、Array
をパラメータとして受信する関数があると仮定するが、keys
を含むObject
を返し、各key
は対応する数値を指す.これもfunctor
である.JavaScript
では、filter
はfunctor
です.彼女は相変わらずArray
に戻りますが、forEach
は違います.彼女はundefined
に戻ります.これは、forEach
には「入力パラメータを維持するデータ構造」がないということです.Functors
は数学で「homomomorphiss between categories」という概念については分かりませんが、大丈夫です.それぞれ単語を変えて読みます.F
は、2つの一般関数f
とg
の組み合わせとして見なされてもよい.F(f . g) = F(f) . F(g)
.
は、組み合わせを表している.すなわち、functors
は、合成特性を保存しなければならない.この方程式に基づいて、関数が
functor
かどうかの結論を出すことができます.アラy Functor
先ほど私達は
map
を見ましたが、Array
のfunctor
です.次にArray.map
がfunctor
であることを証明します.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 ]
見てくださいあなたがどう書くかによって、結果は同じです.したがって、map
はfunctor
です.他の
functors
を試してみます.functors
によってもたらされるパラメータのタイプは、任意のタイプであってもよく、彼女の値を分解して、新しいデータ構造に戻る方法があるならば.String Functor
OKです.
string
を処理できるfunctor
を書いてもいいですか?まず問題を書きます.一つの
string
を分解してもいいですか?必要ですよ.もし一つのstring
を一つのArray of chars
としたら、分解してもいいですか?だから、問題はあなたがどう考えているかにあります.そして、
char
の各々が実はinteger
のchar 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 Funtor
JavaScript
では、関数は一等公民である.関数は他のどのタイプのようにも使えるという意味です.ですから、関数にサービスする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 Functionfunction 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
map
はfunctor
として、Type Signature
はhandler
のType Signature
に依存している.例えば、map
とplus1
を組み合わせて使うと、彼女のType Signature
は次のようになります.map: [int] -> [int]
ただし、handler
のType Signature
は前後一致する必要がないので、以下のようにする.f: int -> string
map
のType Signature
もいいです.map: [int] -> [string]
すなわち、タイプの変化は、functor
の関数合成特性に影響を与えない.一般に、functor
のType Signature
は、このように定義されてもよい.F: A -> B
たとえば、map
は数値配列に入ることができますが、文字列配列を返します.彼女は相変わらずfunctor
です.Monads
は特別なタイプのfunctor
であり、以下のように定義されている.M: A -> A
詳細は次回をご覧ください.原文の住所:Funtional JavaScript-functors