[解決済み] 民話とラムダはなぜ違うのか?
疑問点
javascriptのFPをDrBooleanのものを読んで勉強しています。 本 .
関数型プログラミングのライブラリを探し回った。その結果、RamdaとFolktaleを見つけました。どちらも関数型プログラミングライブラリだと言っています。
しかし、両者は全く違うものです。
-
ラムダ リストを扱うためのユーティリティ関数である map, reduce, filter や、 純粋な関数である curry, compose が含まれているようです。モナドやファンクタを扱うものは含まれていない。
-
民話 は、リストや関数のユーティリティは含まれていません。モナドのようなjavascriptの代数的な構造を実装しているようです。Maybe, Task...
実はもっと多くのライブラリを見つけたのですが、どれもこの2つのカテゴリに分類されるようです。UnderscoreやlodashはRamdaのようなものです。ファンタジーランドやポイントフリーファンタジーはfolktaleのようなものです。
これらの全く異なるライブラリは、両方とも 機能的 と呼ぶことができますか? もしそうなら、何がそれぞれを機能的なライブラリにしているのでしょうか?
どのように解決するのですか?
機能的な特徴
何が関数型プログラミングや関数型ライブラリを定義するのか、明確な境界線はありません。 関数型言語のいくつかの機能は、Javascriptに組み込まれています。
- ファーストクラス、高階関数
- ラムダ/匿名関数、クロージャ付き
その他は、多少の注意を払えばJavascriptで実現することが可能です。
- 不変性
- 参照透過性
さらに他のものは ES6 の一部であり、部分的または完全に今すぐ利用可能です。
- コンパクトな、簡潔な、関数
- テールコール最適化による高性能な再帰処理
その他にも、Javascriptの通常の範囲を超えているものがたくさんあります。
- パターン マッチング
- 遅延評価
- ホモイコニシティ
ライブラリは、サポートしようとする機能の種類を選択することができ、それでも合理的に "functional"と呼ぶことができます。
ファンタジーランドの仕様
ファンタジーランド
は、数学のカテゴリー理論や抽象代数から関数型プログラミングに移植された多くの標準的な型の仕様であり、次のような型があります。
モノイド
,
ファンクタ
そして
モナド
. これらの型はかなり抽象的であり,より身近な概念を拡張したものです. 例えば、ファンクタは
map
に渡すことができるコンテナです。
map
を使うことができます。
Array.prototype.map
.
民話
民話 は、Fantasy-land仕様の様々な部分を実装した型のコレクションであり、付随するユーティリティ関数の小さなコレクションでもあります。 これらの型は、以下のようなものです。 たぶん , どちらか , タスク (他の場所で Future と呼ばれているものに非常に似ており、Promise よりも合法的ないとこです)、および バリデーション
FolktaleはおそらくFantasy-land仕様の最も有名な実装であり、よく知られています。 しかし、決定的な、あるいはデフォルトの実装というものはありません。Fantasy-landは抽象的な型を指定しているだけで、実装はもちろんそのような具体的な型を作成する必要があります。 関数型ライブラリであるというFolktaleの主張は明確で、関数型プログラミング言語で一般的に見られるデータ型を提供し、関数的な方法でプログラミングすることを実質的に容易にするものです。
この例は Folktaleドキュメント ( ノート : 最近のバージョンのドキュメントにはありません) が、どのように使用されるかを示しています。
// We load the library by "require"-ing it
var Maybe = require('data.maybe')
// Returns Maybe.Just(x) if some `x` passes the predicate test
// Otherwise returns Maybe.Nothing()
function find(predicate, xs) {
return xs.reduce(function(result, x) {
return result.orElse(function() {
return predicate(x)? Maybe.Just(x)
: /* otherwise */ Maybe.Nothing()
})
}, Maybe.Nothing())
}
var numbers = [1, 2, 3, 4, 5]
var anyGreaterThan2 = find(function(a) { return a > 2 }, numbers)
// => Maybe.Just(3)
var anyGreaterThan8 = find(function(a) { return a > 8 }, numbers)
// => Maybe.Nothing
ラムダ
ラムダ (免責事項:私は作者の一人です)は、非常に異なったタイプのライブラリです。 新しい型を提供してくれるわけではありません。 1 その代わり、既存の型の操作を容易にするための関数を提供します。 小さな関数をより大きな関数に合成する、不変のデータを扱う、副作用を避ける、といった概念を中心に構築されています。
Ramdaは特にリストに対して動作しますが、オブジェクトや、時には文字列に対しても動作します。 また、Folktaleや他のFantasy-landの実装と相互運用できるように、多くの呼び出しをデリゲートしています。 例えば、Ramdaの
map
関数と同じような動作をします。
Array.prototype
というように
R.map(square, [1, 2, 3, 4]); //=> [1, 4, 9, 16]
. しかし、Folktaleの
Maybe
は幻想郷を実装しているからです。
Functor
仕様で、map も指定されているので、Ramda の
map
を使うこともできます。
R.map(square, Maybe.Just(5)); //=> Maybe.Just(25);
R.map(square, Maybe.Nothing); //=> Maybe.Nothing
Ramdaは関数型ライブラリとして、関数の合成を容易にすること、データに変異を与えないこと、純粋な関数だけを表示することを特徴としています。 Ramdaの典型的な使い方は、より小さな関数を組み合わせてより複雑な関数を構築することです。 Ramdaの哲学
// :: [Comment] -> [Number]
var userRatingForComments = R.pipe(
R.pluck('username') // [Comment] -> [String]
R.map(R.propOf(users)), // [String] -> [User]
R.pluck('rating'), // [User] -> [Number]
);
その他のライブラリ
underscoreやlodashはRamdaに似ています。ファンタジーランド、ポイントフリーファンタジーはfolktaleに似ています。
それはあまり正確ではありません。 まず第一に、ファンタジーランドは、ライブラリが様々なタイプのために実装することを決定できる、単なる仕様です。 Folktaleはその仕様の多くの実装のうちの1つで、おそらく最も充実したものであり、最も成熟したものの1つであることは間違いありません。 ポイントフリーファンタジー と ラムダファンタジー は他にもあり、また 他にもたくさん .
アンダースコア と ロダッシュ は、表面的にはRamdaと同じで、Folktaleのようなものよりもずっとまとまりのない、多くの機能を提供する福袋のようなライブラリです。 また、具体的な機能についても、Ramdaと重複していることが多い。 しかし、より深いレベルでは、Ramdaはこれらのライブラリとはまったく異なる関心を持っています。 Ramdaの最も近いいとこは、おそらく、以下のようなライブラリでしょう。 FKit , Fnuc そして wu.js .
ビルビー は、Ramdaが提供するような多くのツールと、Fantasy-landと同じタイプのものを提供する、独自のカテゴリーに属するものです。 (Bilbyの作者はFantasy-landの原作者でもある)。
あなたの呼びかけ
これらのライブラリは、機能的アプローチと機能的コミットメントの度合いに大きな違いがあるものの、すべて機能的と呼ばれるにふさわしいものです。
これらのライブラリのいくつかは、実際に一緒にうまく動作します。 RamdaはFolktaleや他のFantasy-landの実装とうまくいくはずです。 彼らの関心はほとんど重なっていないので、本当に衝突することはありませんが、Ramdaは相互運用を比較的スムーズにするのに十分な働きをしてくれます。 これは、おそらく他の組み合わせには当てはまりませんが、ES6のよりシンプルな関数構文が、統合の苦労を軽減してくれるかもしれません。
ライブラリの選択、あるいは スタイル の選択は、あなたのプロジェクトと好みによって異なります。 良い選択肢がたくさんあり、その数は増え続けており、その多くは大きく改善されています。 JSで関数型プログラミングを行うには良い時期です。
1 まあ、サイドプロジェクトがあるんですけどね。 ラムダ・ファンタジー があり、Folktale と同じようなことをしていますが、これはコアライブラリの一部ではありません。
関連
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] let "と "var "の使い分けは?
-
[解決済み] なぜGoogleはJSONレスポンスにwhile(1);を前置するのでしょうか?
-
[解決済み] callとapplyの違いは何ですか?
-
[解決済み] URLを新しいタブで開く(新しいウィンドウではない)
-
[解決済み] JSONPとは何か、なぜ作られたのか?
-
[解決済み] なぜ ++[[]][+[] +[+[]] は "10" という文字列を返すのでしょうか?
-
[解決済み] 上級者向けJavaScript。この関数はなぜ括弧でくくられるのですか?重複
-
[解決済み] <Enter>でjQuery UIダイアログを送信する
-
[解決済み] JavaScriptのtoString()関数をオーバーライドして、デバッグ用に意味のある出力を提供することは可能でしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] JSのDateからDay名
-
[解決済み] ジェスト あるクラスの特定のメソッドをモックする方法
-
[解決済み] 上級者向けJavaScript。この関数はなぜ括弧でくくられるのですか?重複
-
[解決済み] Javascriptによるタッチスクリーンデバイスの検出
-
[解決済み] react-routerのハッシュフラグメントからクエリパラメータを取得する
-
[解決済み] CORS: 認証モードは 'include' です。
-
[解決済み] Prototypeを使ってtextareaを自動サイズ調整するには?
-
[解決済み] jQueryを使用して、すべてのクリックイベントハンドラを削除するにはどうすればよいですか?
-
[解決済み] <ng-content>が空かどうかを確認する方法は?(これまでのAngular 2+で)
-
[解決済み] JavaScriptデータフォーマット/プリティプリンタ