あなたは関数型プログラマになりたい(パート3)

関数型プログラミングの概念を理解するための最初の一歩を踏み出すことは、最も重要で、時には最も困難な手順です。しかし、そうである必要はありません。正しい視点ではありません。

前のパート:パート1、パート2

機能構成

プログラマーとして、私たちは怠け者です。私たちは何度も何度も書いたコードをビルド、テスト、デプロイしたくありません。

私たちは常に、一度作業を行う方法と、それを再利用して他のことをする方法を見つけようとしています。

コードの再利用は素晴らしいように聞こえますが、達成するのは困難です。コードを具体的にしすぎると、再利用できなくなります。一般化しすぎて、そもそも使いづらいかもしれません。

したがって、必要なのは、2つのバランスをとることです。これは、より複雑な機能を構築するためのビルディングブロックとして使用できる、小さく再利用可能なピースを作成する方法です。

関数型プログラミングでは、関数はビルディングブロックです。非常に具体的なタスクを実行するためにそれらを作成し、Lego™ブロックのようにそれらをまとめます。

これは関数構成と呼ばれます。

それでは、どのように機能しますか? 2つのJavaScript関数から始めましょう。

var add10 = function(value){
    戻り値+ 10。
};
var mult5 = function(value){
    戻り値* 5;
};

これは冗長すぎるため、太い矢印表記を使用して書き直しましょう。

var add10 = value => value + 10;
var mult5 = value => value * 5;

良いですここで、値を取り、それに10を加算し、結果に5を乗算する関数も必要だと想像してみましょう。

var mult5AfterAdd10 = value => 5 *(値+ 10)

これは非常に単純な例ですが、この関数を最初から記述する必要はありません。最初に、括弧を忘れるなどの間違いを犯す可能性があります。

第二に、10を追加する関数と5を乗算する別の関数が既にあります。すでに記述したコードを記述しています。

代わりに、add10とmult5を使用して新しい関数を作成しましょう。

var mult5AfterAdd10 = value => mult5(add10(value));

既存の関数を使用してmult5AfterAdd10を作成しましたが、より良い方法があります。

数学では、f∘gは関数合成であり、「fはgで構成されています」、より一般的には「f after g」と読みます。したがって、(f∘g)(x)は、xを使用してgを呼び出した後にfを呼び出すか、単にf(g(x))と同等です。

この例では、mult5∘add10または「mult5 after add10」があるため、関数の名前はmult5AfterAdd10です。

それがまさに私たちがしたことです。値または単にmult5(add10(value))でadd10を呼び出した後、mult5を呼び出しました。

Javascriptは関数構成をネイティブに実行しないため、Elmを見てみましょう。

add10値=
    値+ 10
mult5値=
    値* 5
mult5AfterAdd10値=
    (mult5 << add10)値

<<内接演算子は、Elmで関数を構成する方法です。データがどのように流れているかを視覚的に把握できます。まず、値がadd10に渡され、その結果がmult5に渡されます。

mult5AfterAdd10の括弧、つまり(mult5 << add10)に注意してください。それらは、値を適用する前に関数が最初に構成されることを確認するためにあります。

この方法で好きなだけ関数を作成できます:

f x =
   (g << h << s << r << t)x

ここで、xは関数tに渡され、その結果はrに渡され、その結果はsに渡されます。 Javascriptで似たようなことをすると、g(h(s(r(t(x)))))のようになります。

ポイントフリー表記

Point-Free Notationと呼ばれるパラメーターを指定することなく、関数を記述するスタイルがあります。最初は、このスタイルは奇妙に思えますが、続行すると、簡潔さを理解できるようになります。

mult5AfterAdd10では、値が2回指定されていることがわかります。パラメータリストに1回、使用時に1回。

-これは1つのパラメーターを予期する関数です
mult5AfterAdd10値=
    (mult5 << add10)値

ただし、コンポジションの右端の関数であるadd10は同じパラメーターを想定しているため、このパラメーターは不要です。以下のポイントフリーバージョンは同等です。

-これも1つのパラメーターを予期する関数です
mult5AfterAdd10 =
    (mult5 << add10)

ポイントフリー版を使用することには多くの利点があります。

まず、冗長パラメーターを指定する必要はありません。そして、それらを指定する必要がないため、すべての名前を考える必要はありません。

第二に、冗長性が少ないため、読みやすく、推論しやすくなります。この例は単純ですが、より多くのパラメーターを受け取る関数を想像してください。

楽園でのトラブル

これまで、関数合成がどのように機能するか、簡潔さ、明快さ、柔軟性のためにポイントフリー表記で関数を指定する方法について見てきました。

それでは、これらのアイデアを少し異なるシナリオで使用して、どのように変化するかを見てみましょう。 add10をaddに置き換えたとします。

x y =を追加
    x + y
mult5値=
    値* 5

これら2つの関数だけでmult5After10を記述する方法は?

読む前に少し考えてみてください。真剣に。について考える。やってみてください。

さて、実際に時間をかけて考えた場合、次のような解決策を思いついたかもしれません。

 -  これは間違っています !!!!
mult5AfterAdd10 =
    (mult5 <<追加)10

しかし、これはうまくいきません。どうして? addは2つのパラメーターを取るため。

Elmでこれが明らかでない場合は、これをJavascriptで記述してください。

var mult5AfterAdd10 = mult5(add(10)); //これは機能しません

このコードは間違っていますが、なぜですか?

ここでadd関数は2つのパラメーターのうち1つしか取得していないため、誤った結果がmult5に渡されます。これにより、誤った結果が生成されます。

実際、Elmでは、コンパイラはそのような誤った形式のコード(エルムの素晴らしい点の1つ)を書くことさえできません。

もう一度試してみましょう。

var mult5AfterAdd10 = y => mult5(add(10、y)); //ポイントフリーではありません

これは無意味ではありませんが、おそらくこれで生きることができるでしょう。しかし、今では機能を組み合わせただけではありません。新しい関数を書いています。また、これがより複雑になる場合、例えばmult5AfterAdd10を他の何かで構成したい場合、私は本当のトラブルに陥ります。

したがって、これら2つの関数を結合できないため、関数合成の有用性は限られているように見えます。それはとても強力だからです。

どうすればこれを解決できますか?この問題を解決するには何が必要でしょうか?

本当に素晴らしいことは、add関数にパラメーターの1つだけを事前に与え、その後mult5AfterAdd10が呼び出されたときに2番目のパラメーターを取得する方法がある場合です。

方法があり、カリーと呼ばれています。

私の脳!!!!

今のところ十分です。

この記事の以降の部分では、カリー化、一般的な機能関数(マップ、フィルター、折り畳みなど)、参照の透明性などについて説明します。

次:パート4

これが気に入ったら、下のをクリックして、他の人がこれを中に表示するようにします。

ElmのFunctional Programmingを使用してWebアプリの開発を学び、支援するWeb開発者のコ​​ミュニティに参加したい場合は、FacebookグループのLearn Elm Programming https://www.facebook.com/groups/learnelm/をご覧ください。

私のTwitter:@cscalfani