【関数型言語】使いどころ

関数型言語の勉強中。関数型言語とはどういうものかを理解するのに四苦八苦。命令型言語と比べてどんな特徴があるのかと言う観点で学んでいる。しかし、本当に知りたいのは、どういう場合に関数型言語使うべきかということ。

ナップサック問題、サラリーマン巡回問題など、グラフ理論を使った開放では漸化式が出てくる。このような場合、関数型言語だとすっきり実装することが、できそう。

【関数型言語】学ぶ目的・メリット

単なる好奇心ももちろんある。関数型言語って何ぞ?

実用的な観点として、次のようなもの

 

最近はプロセッサがマルチコアになり、またスケーラブルなシステムにするためにクラウド上にクラスタを作って動かすシステムが増えている。処理速度を上げるために、並列処理を進めたい。

メジャーな言語(Java, C++など)は、スレッド間でデータを排他処理しなければならないが、適切に設計するのは難しい。

 

その点、関数型言語は並列化が容易だ。(らしい)それは、すべての関数とデータがイミュータブル(immutable 不変)なので、排他制御が不要になるから。

 

という理屈はわかった。実感がわかない。なので、並行処理を必要とするアプリケーションで、オブジェクト指向言語関数型言語で、詳細設計・実装がどのように変わるか、比較してみたい。(いつか)

【関数型言語】継続渡し(CPS:Continuation-passing style)

計算途中の文脈(コンテキスト)を保存し、任意のタイミングで計算を途中から継続できるようにするしくみらしい。

ここで生じた疑問。

コンテキストとは具体的にはどのような内容なのか?

OSのコンテキストスイッチの場合、

になる。クロージャーを持っている言語ならば、CPSを実現できるらしい。

C++ならば、ラムダ式でキャプチャーした内容を保存できる、ということだろう。だとすると、レジスタの値は保存されない。ローカル変数と引数はスタックに保存されているが、これらはラムダ式で使える。あ、C++ラムダ式て、その場で実行するのではなく、あとで実行ってできたっけ?

【関数型言語】ファンクター(関手)

「すごいHaskell楽しく学ぼう!」

第11章「ファンクターからアプリカティブファンクターへ」

11.1 「帰ってきたファンクター」より。

ファンクターとは関数で写せるもののことです。

 ファンクターの型クラスメソッドは一つだけで、それは fmap です。fmap の型は fmap :: (a -> b) -> f a -> f b です。

 fmap については2通りの考え方ができます。

  • fmap は関数とファンクター値をとって、その関数でファンクター地を写して返すものである。
  • fmap は値から値への関数をとって、それをファンクター値からファンクター値への関数に持ち上げたものを返す関数である。

 

【関数型言語】Haskell と Scala の畳み込み関数

ScalaHaskell を比較しながら学んでいる。畳み込み関数について、全く違った表記があった。 

  • Scala では foldLeft ではなく foldRight がスタックオーバーフローの危険がある。
  • Haskell では foldr ではなく foldl がスタックオーバーフローの危険がある。

どういうこと?で、ググった。

Scalaの畳み込み関数

、foldLeft は末尾再帰最適化されているのでスタックを消費しないが、(標準の)foldRight は末尾再帰最適化されていないのでスタックを消費してしまう。foldLeftを使って  foldRight を実装すると、スタックオーバーフローを回避できる。

Haskellの畳み込み関数

Haskell はデフォルトで遅延評価なので、foldl でもスタックを消費してしまうらしい。

回避するには、正格(遅延評価しない)な関数 foldl' を使う。かと思いきや、Haskell の場合は foldr のほうが計算量が少ない(高速)という記述もあり混乱中。foldr はスタックオーバーフローしないのか?「foldl は無限リストを扱えないが、foldr は無限リストを扱える」らしい。このこととスタックの使い方はどうなっている?

2018年01月04日のツイート

【関数型言語】IntelliJ での fpinscala の練習問題を解く環境

演習問題をビルド・実行する環境をどうしたものかと思っていた。演習問題以外のソースコード(テキストに載っている List や Option など)を打ち込まないとビルドできないからだ。だが、いいページを見つけた。感謝。

qiita.com

ubuntu でも問題なく下記のコマンドを実行できた。

$ git clone https://github.com/fpinscala/fpinscala.git

$ cd fpinscala

$ chmod a+x ./sbt

$ cat > project/plugins.sbt << EOS > addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")

> EOS

$ ./sbt gen-idea

 迷ったのはこの後。Idea で開くプロジェクトの場所がわからなかった。プロジェクトファイルっぽいのがどこに出来たのかわからなかった。仕方ないので、 git clone からやり直した。すると、 clone したフォルダの直下に .idea フォルダができていた。

IntelliJ idea で Open Project で fpinscala フォルダを指定した。

その次に迷ったのは、

exercises ディレクトリを右クリックして Compile Module 'exercises' を実行する。

 の部分。原因は、IntelliJ Idea の起動画面にプロジェクトペインがなかったこと。

[View][Tool Windows][Project] でプロジェクトペインを表示できた。そこで指示通りに exercises ディレクトリを右クリックすると、 Compile Module 'exercises' を選択できた。

 

そして、指示通りに

exercises ディレクトリに worksheets ディレクトリを作成する。worksheets ディレクトリに 02_GettingStarted.sc というような名前で Scala Worksheet を作成する。

作成した Worksheet に練習問題の解答になる関数定義とその関数呼び出しを書く。右側に出力される結果を確認する。

 確かに、左側に演習問題の解答コードを記入すると、右側に実行結果が表示された。 便利!

 

f:id:kzono:20180102232712p:plain