関数型プログラミングの概要の概要

関数型プログラミングを始めて間もないので、内容が結構微妙だったりしますがご了承願います。
勉強しつつ見返しつつ、おかしなところを見つけたら随時追記修正します。

関数型プログラミングとは

関数型プログラミングは、雑に説明すると関数の組み合わせのみでプログラムを記述するプログラミングパラダイムの一つです。

for文とかないんです。
変数への再代入なんかもありません。

さて、for文も使わずにどうやってプログラムを書くんだろう…。

他のパラダイムとの比較

「関数型」とよく対比されるものに「手続き型」 、「オブジェクト指向」があります。

手続き型言語は、実行させたいコードを順々に書いていくようなイメージです。
オブジェクト指向は、関心事ごとに分けてオブジェクトを作って書いていくようなイメージです。

各思想の紹介
【参考】手続き型とオブジェクト指向と関数型 – まこたん(makotan)の日記

Pythonで手続き型と関数型のプログラムを書いて比較してる記事。良い記事。
【参考】関数型プログラミング入門 | POSTD

オブジェクト指向と関数型を比較してる記事
【参考】オブジェクト指向と関数型で副作用の扱いが違うって知ってた? – セカイノカタチ

関数型プログラミングのなにがうれしいのか

副作用がない

副作用ってなんですか?

普段使う言葉としての「副作用」だと、何かの薬を飲んだときに、その薬の目的の効用とは別に付随してくる良くない作用のことですね。

関数においては、引数、戻り値を効用として、それ以外の作用を副作用と呼びます。
関数型プログラミングにおける「副作用」はその付随効果が良くも悪くも、それを「副作用」と呼びます。

ここで言う「関数」とは、「純粋関数」のことです。
純粋関数とは、「引数が一つ決まれば、絶対に同じ値がreturnされるような関数」のことです。

普通そうじゃね?って思う人は以下の純粋関数じゃない関数のコードをご覧ください。
例えばこういうもの。

このhoge関数は入力のx以外にもnumという変数の影響を受けます。
ということは、hoge関数に渡す引数を「1」と固定したとしても、時と場合に依っては3が返ってきたり、-5が返ってきたりする可能性がありますね。

上の例では、引数以外に影響のあるものnumが副作用になります。

他にはこういうもの。

このnowDate関数は、引数は取らず内部で実行時の時刻を取得し、出力しています。

これも実行するタイミングで返ってくる値が変わるので純粋関数ではありません。
副作用とはこういったものです。

純粋関数はこういった副作用を全て取り除いた関数です。
引数が一つ決まれば、戻り値も一つに決まります。

このような純粋関数の何がいいかと言うと、

  • 思わぬところで値の変更がなくなるので、バグに遭遇しにくくなる
  • 関数の入出力を見るだけでシステムがどのように動くのかを完全に把握できる
  • ブラックボックステストがしやすくなる

賛否両論ありそうですが、 「手続き型で書かれたコードは、人間にとってではなくコンピュータにとってわかりやすいもの」と書かれてた記事もありました。

要するに、手続き型のコードは「状態」を追うのが大変だけど、関数型にはそういうものはない。ということです。

副作用についての話にこんな記事もありました。
【参考】「関数型プログラミングって何?」日本語訳 – Okapies’ Archive

抽象的でシンプルなコードを書ける

小さな関数を組み合わせて、処理を記述していくので、コード量自体が少なくなります。
そうすると見やすくなるし、修正もしやすく、さらにテストもしやすくなります。

例えばよく例に出されるものにHaskellのクイックソートのプログラムがあります。

Pythonの場合

【参考】ソートアルゴリズムと Python での実装 – Qiita

Haskellの場合

【参考】いつからHaskellの5行クイックソートが遅いと錯覚していた? – Qiita

こんなに短くなりました。
短く書けることは良いことなのです。人間が理解しやすくなります。

Haskellは状態遷移を値の再代入で行うのではなく、 関数の組み合わせで、今回の場合は再帰させることでプログラムを組んでいきます。

こうすることでプログラムの動作をわかりやすくし、テストやデバッグがしやすくなります。

関数型プログラミングといえば的な言語

関数型のプログラミング言語は結構たくさんあります。
以下ではその一部を紹介します。

 

  • Haskell 代表的存在で純粋関数型言語。
  • OCaml INRIA製、速い
  • Coq INRIA製、定理証明支援系
  • Erlang ホットスワップ、耐障害性がある
  • Scala オブジェクト指向+関数型プログラミング。Javaと相性がいい

JavaScriptへの応用。react,reduxとの関係性

僕が最近触っているJavaScriptにも関数型プログラミングが取り入れられたりもしています。
JSで関数型プログラミングを支援する以下のようなライブラリがあったりします。

  • underscore.js
  • lodash.js
  • ramda.js

jsで関数型プログラミングを学ぼうみたいな本に、こんなんとか、こんなんがあったり、 ブログ記事でも、こんなのこんなのがあったり、結構いっぱいあります。

以下も別の記事にして書きますが、 ReactにもHiger-order Componentsといった高階関数ならぬ高階コンポーネントがあったり、 Reduxも関数型言語のElmアプリのアーキテクチャを参考にデザインされています。

意識してなかったところにも実は結構取り入れられたりもしています。

関連

関連して、「リアクティブプログラミング」というものもあります。

それと関数型プログラミングをかけ合わせた「関数型リアクティブプログラミング(functional reactive programming)」というのもあったりします。

このFRPとReactをかけ合わせた関数型(FRP)Reactなんてものもあったりするみたいです。

【参考】関数型ReactでビジュアルFizzBuzz – Qiita

まだまだ世界は広いようです。
こちらもまた時間をとって勉強したいです。

参考一覧

今注目されている!関数型プログラミングとは【初心者向け】 | TechAcademyマガジン ocaml-zippy-tutorial-in-japanese/whyfp.md at master · camlspotter/ocaml-zippy-tutorial-in-japanese