なぜ民話とラムダがそれほど違うのですか?


96

DrBooleanの本を読んでJavaScript FPを学んでいます。

関数型プログラミングライブラリを探しました。ラムダと民話を見つけました。どちらも関数型プログラミングライブラリであると主張しています。

しかし、それらはとても異なります:

  • Ramdaには、リストを処理するためのユーティリティ関数(マップ、リデュース、フィルター、およびピュア関数:カレー、コンポーズ)が含まれているようです。モナド、ファンクターを扱うものは何も含まれていません。

  • ただし、Folktaleにはリストや関数のユーティリティは含まれていません。それはモナドのようなjavascriptでいくつかの代数構造を実装しているようです:多分、タスク...

実際、私はより多くのライブラリーを見つけました。それらはすべて2つのカテゴリーに分類されるようです。アンダースコアとロダッシュはラムダのようなものです。ファンタジーランド、ポイントフリーファンタジーは民話のようなものです。

これらの非常に異なるライブラリの両方を機能的と呼ぶことができますか?


1
ニーズとスタイルに適合し、十分に文書化されているものを使用してください
charlietfl

1
特にJSでは、「関数型プログラミング」には一般的に意図されている3つの意味があることがわかりました。1.配列などのセットで高次の純粋関数を使用します。例[1,2,3].map(fnSquare).reduce(fnSum)2.主に学術的な "look ma no var " Y-combinator-esque構造。3. Function.prototypeなどの他の機能の動作を変更するために使用var isMissingID=fnContains.partial("id").negate();
dandavis '

10
Ramdaの作者:Ramdaは、かなり低レベルのユーティリティライブラリです。これは、JSで特定の関数スタイルをより簡単にすること、特に関数を作成することで機能することを目的としています。Ramdaは、Folktaleなどの実装を含め、FantasyLand仕様でうまく機能します。これらのライブラリは、多少異なる目的で設計されています。これらは、一般的な抽象データ型を認識し、それらへの一貫したアクセスを可能にすることを中心に構築されています:モノイド、ファンクター、モナドなど。Ramdaは彼らと協力し、いくつかを作成するためのサイドプロジェクトを持っていますが、あなたが言うように、それは非常に異なる焦点です。
Scott Sauyet、2015年

1
@KeithNicholas:はい、Gitter Roomがあります
Scott Sauyet

2
Sanctuaryもご覧ください-github.com/plaid/sanctuary これはramdaに基づいていますが、ファンタジーの土地タイプもカバーしています。
arcseldon 2016

回答:


179

機能的特徴

関数型プログラミングまたは関数型ライブラリを定義するものの明確な境界はありません。関数型言語のいくつかの機能はJavaScriptに組み込まれています。

  • ファーストクラスの高階関数
  • ラムダ/無名関数、クロージャー付き

他のものは、JavaScriptでいくつかの注意を払って達成することが可能です:

  • 不変性
  • 参照の透明性

さらに、ES6の一部であり、現在、部分的または完全に利用可能なものもあります。

  • コンパクトで簡潔な機能
  • 末尾呼び出しの最適化によるパフォーマンスの高い再帰

そして、Javascriptの通常の範囲を本当に超えている他の多くがあります:

  • パターンマッチング
  • 遅延評価
  • 同型性

そうすれば、ライブラリーは、サポートしようとしている機能の種類を選んで選択することができ、それでも「機能的」と呼ぶことができます。

ファンタジーランド仕様

ファンタジーランドは、関数型プログラミングに数学カテゴリ理論と抽象代数学から移植された標準タイプの数のための仕様である、などの種類モノイド関数形、およびモナド。これらのタイプはかなり抽象的で、おそらくより馴染みのある概念を拡張します。たとえば、ファンクタはmap、関数を使用して移動できるコンテナであり、配列mapを使用して配列を移動できますArray.prototype.map

民話

Folktaleは、Fantasy-land仕様のさまざまな部分を実装するタイプのコレクションと、付随するユーティリティ関数の小さなコレクションです。これらのタイプは、MaybeEitherTask(他の場所ではFutureと呼ばれるものと非常に似ており、Promiseのより適法ないとこ)とValidationのようなものです。

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

ラムダ

Ramda(免責事項:私は作成者の1人です)は、非常に異なるタイプのライブラリーです。新しいタイプは提供されません。1 代わりに、既存の型の操作を簡単にする関数を提供します。これは、小さな関数を大きな関数に構成する、不変データを処理する、副作用を回避するという概念に基づいて構築されています。

Ramdaは特にリストで動作しますが、オブジェクトにも動作し、文字列にも動作します。また、Folktaleまたはその他のファンタジーランドの実装と相互運用できるように、その呼び出しの多くを委任します。例えば、RAMDAのmap機能は、上の1と同様に動作するArray.prototypeので、R.map(square, [1, 2, 3, 4]); //=> [1, 4, 9, 16]。ただし、Folktale はマップも指定MaybeするFantasy-land Functor仕様を実装しているため、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]
);

その他の図書館

実際、私はより多くのライブラリーを見つけました、それらはすべて2つのカテゴリーに分類されるようです。アンダースコア、ロダッシュはラムダに非常に似ています。ファンタジーランド、ポイントフリーファンタジーは民話のようなものです。

それは本当に正確ではありません。まず第一に、Fantasy-landは、ライブラリがさまざまなタイプに実装することを決定できる仕様にすぎません。Folktaleは、その仕様の多くの実装の1つであり、おそらく最も総合的なものであり、確かに最も成熟したものの1つです。 ポイントフリーファンタジーラムダファンタジーは他にもあり、他にもたくさんあります

Underscorelodashは、見た目Ramdaに似ていますが、グラブバッグライブラリであり、Folktaleのようなものよりもまとまりのない多数の関数を提供します。そして、特定の機能でさえラムダの機能と重複することがよくあります。しかし、より深いレベルでは、ラムダはこれらのライブラリとは非常に異なる懸念を抱いています。Ramdaに最も近いいとこは、おそらくFKitFnuc、およびWu.jsなどのライブラリです。

Bilbyは独自のカテゴリに属し、Ramdaが提供するツールなどの多数のツールと、Fantasy-landと一致するいくつかのタイプの両方を提供しています。(ビルビーの作者は、ファンタジーランドの原作者でもあります。)

あなたの電話

これらのライブラリはすべて、機能的アプローチと機能的コミットメントの程度が大きく異なりますが、機能的と呼ばれる権利があります。

これらのライブラリのいくつかは、実際には一緒にうまく動作します。RamdaはFolktaleまたは他のFantasy-land実装でうまく機能するはずです。それらの懸念がほとんど重ならないため、それらは実際には競合しませんが、Ramdaは相互運用を比較的スムーズにするのに十分です。これは、選択できる他のいくつかの組み合わせではおそらくあまり当てはまりませんが、ES6のより単純な関数構文は、統合の手間をいくらか取り除くかもしれません。

ライブラリの選択、または使用するライブラリのスタイルさえも、プロジェクトと設定に依存します。利用できる優れたオプションはたくさんあり、その数は増えており、その多くは大幅に改善されています。JSで関数型プログラミングを行う良い機会です。


1さて、サイドプロジェクト、Folktaleと同じようなことをするラムダファンタジーがありますが、それはコアライブラリの一部ではありません。


1
ES6にYieldの導入による遅延評価の機能があると言っても過言ではありませんか?developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
マルセル・ラモット

8
いいえ 。またはyieldによって行われる一種の遅延リスト処理を簡単にします。しかし、それは言語レベルの怠惰を助けません。 JSの最初の値を加算し、次いでsomeFuncにパラメータとしてその結果を供給する。Haskellの同等のものはそれを行いません。呼び出された関数がその値を使用しない場合、加算は実行されません。最終的にそれを使用する場合、その結果が必要になるまで計算される式と見なされます。強制するようなことをしないと(IOなど)、実際に計算が実行されることはありません。Lazylz.jssomeFunc(a + b)ab
Scott Sauyet、2015

@ScottSauyetおそらく、たとえば、「遅延評価」はES6ジェネレーターを介して利用できると主張するかもしれません-多くのJSフレームワークは「怠惰」特性を持っています-RxJs、ImmutableJsなど
arcseldon

8
この回答は、DrBooleanの本の章またはセクションである必要があります。:)
Seth

1
Ramdaのドキュメントでは、JSがリストに提供する最も近いもの、つまり密集した配列の省略形として「リスト」を使用する傾向があります。これらは純粋なリストとは異なるパフォーマンス特性を持ち、もちろん多少異なるAPIですが、ほとんど同じ目的で使用でき、Ramdaで利用できる最も近いネイティブ(github.com/funkia/listを参照)タイプです概念的には純粋なリストを操作したいAPI。Cスタイルの配列はJSの配列よりも標準的なものではなく、数学的な配列に本当に近いものではないので、私は真実ではない配列のポイントを主張しますが、それは小さなポイントです。
Scott Sauyet
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.