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

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

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

関数型プログラミングとは、「Functional Programming」のことです。
FPとか略されたりします。
説明になってませんね。

めっちゃ雑で、興味を惹くような答え方をすると、
関数の組み合わせでプログラムを記述するスタイルのことです。

for文とかないんです。変数への再代入なんかもありません。
さて、for文も使わずにどうやってプログラムを書くんだろう・・

どのようなものか

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

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

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

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

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

よくよく考えれば僕はオブジェクト指向もいまいちわかってないなぁ・・。

なにがうれしいのか

副作用がない

副作用ってなんですか?
普段使う言葉としての「副作用」だと、何かの薬を飲んだときとかに、その薬の目的の効用とは別に付随してくるよろしくない作用のことですね。
関数においては、引数、戻り値を効用として、それ以外の作用を副作用と呼びます。
この副作用はその付随効果が良くも悪くもそれを副作用です。

ここで言う「関数」とは「純粋関数」のことで、これが何かって言うと、引数が一つ決まれば、絶対に同じ値がreturnされるような関数のことです。
普通そうじゃね?って思う人は以下の純粋関数じゃない関数のコードを見てみてください。

例えばこんなん

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

例えばこんなん

このnowDage関数は、引数は取らず内部で実行時の時刻を取得し、出力しています。
これも実行するタイミングで返ってくる値が変わるので純粋関数ではありません。

副作用とはこういったものです。
純粋関数はこういった副作用を全て取り除いたものです。

こんなふうにした純粋関数の何がいいかと言うと、

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

賛否両論ありそうですが、
「手続き型で書かれたコードは、人間にとってではなくコンピュータにとってわかりやすいもの」と書かれてた記事もありました。
要するに、手続き型のコードは「状態」を追うのが大変だけど、関数型にはそういうものはない。ということです。

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

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

小さな関数を組み合わせて、処理を記述していくので、コード量自体が少なくなります。
そうすると、見やすくなるし、修正もしやすく、さらに、テストもしやすいんです。
例えばよく例に出されるものにHaskellのクイックソートのプログラムがあります。

Pythonの場合

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

Haskellの場合

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

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

Haskellは状態遷移を値の再代入で行うのではなく、
関数の組み合わせで、今回の場合は再帰させることで、プログラムを組んでいきます。
こうすることでプログラムの動作をわかりやすくし、テストやデバッグがしやすくなります。

調べてるとよく出てくるキーワード

関数型プログラミング(というかHaskell)を調べてるとよく出てくるキーワードです。
いまいちわかってないところも多いので羅列だけしておきます。
検索などに役に立てばと思います。

  • 高階関数
  • 遅延評価
  • カリー化
  • ファンクタ
  • アプリカティブ
  • モナド
  • 並列化

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

  • Haskell 代表的存在で純粋関数型言語。文法が少々トリッキー
  • Rust 安全性、速度、並行性にフォーカスしてる言語です。
  • OCaml
  • Erlang 電話交換アプリケーションとか
  • Sacala オブジェクト指向+関数型プログラミング。Javaと相性がいい
  • F#
  • Scheme

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

僕が最近触るJavaScriptにも関数型プログラミングが取り入れられたりもしています。
詳細は別の記事にして書きますが、以下のようなライブラリがあったりします。

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

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

以下も別の記事にして書きますが、
ReactにもHiger-order Componentsといった高階関数ならぬ高階コンポーネントがあったり、
Reduxに関しても、reducerなんて完全に純粋関数です。
意識してなかったところにも実は結構取り入れられたりもしています。

関連

ほぼ理解していませんが、「リアクティブプログラミング」というものもあります。
それと関数型プログラミングをかけ合わせた「関数型リアクティブプログラミング(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

コメントを残す