IGGG Advent Calender 2015のために書いた記事です。
プログラミング言語Haskellを複数に分けて簡単にまとめてみました。
第1回はHaskellの特徴と歴史についてです。
Haskellとは1990年に肥大化した関数型プログラミング言語の「標準語」として設計された言語です。
特徴としては
- 純粋関数型プログラミング言語
- (かなり)強い静的型付
- (世にも珍しい)デフォルトで遅延評価
- 名前の由来は論理学者のハスケル・カリーから
などが挙げられます。
ためしに、超簡単なHaskellコードを見てみましょう。
fact :: Int -> Int
fact 0 = 1
fact n = n * fact (n - 1)
これは階乗をする関数のコードです。
CやJavaのような手続き型の言語と比べると、一風変わった感じに見えるかもしれません。
恐らく、プログラムコードよりは数式に近く感じられると思います。
構文については次回で説明します。
では、Haskellの基本的な性質である、関数型プログラミングとはなんなのでしょうか?
関数型プログラミングとは、プログラム(問題)を「関数」とその組み合わせで記述するプログラミングのコトを指します。
そのため関数型言語(特にHaskell)には
- ラムダ式
- 高階関数
- カリー化
- 遅延評価
- 代数データ型
等の関数の表現力を増すための機能が実装されています。
(ちなみに、これらの 機能 は最近注目され始め、様々な言語へ導入されていますね。)
では、そもそも関数とはなんなのでしょうか?
CやJavaにも関数は出てきますが、それらの指す「関数」と関数型言語の指す「関数」は意味が違います。
- 命令型言語: 特定の命令・手続きに付けられたラベル
- 関数型言語: 写像の意味での数学的な関数
そのため、関数型言語における関数は副作用を持ちません。
副作用 : 状態を変化させることにより、次回以降の結果にまで影響を与える効果のコト
副作用を持たないことを「参照透過性」といい、
参照透過性を持つ言語を「純粋」であると言います。
具体的に言えば、引数が同じなのにもかかわらず、利用するタイミングによって結果が変わる(つまり状態を持つ)関数は「副作用を持つ」となります。
I/O系や関数の静的変数、再代入なんかもアウトですね。
そのため、I/Oは少々苦手なのです(もちろん書けるには書けますよ)。 その代わりに、静的変数や再代入を許さないためバグが混入しにくく、テストや並列化がしやすくなります(なると言われています)。
最後にHaskell が設計されるまでの歴史を記します。
- 1930s: アロンゾ・チャーチが関数の理論を形式化(ラムダ計算)
- 1958: 初の関数型言語「LISP」の登場
- 1966: 初の純粋関数型言語「ISWIM」が設計される
- 1970s: 初の現代的な関数型言語「ML」の登場
- 1980s: 遅延評価に関数する研究が進む
- 1990: 肥大化した関数型言語の機能をまとめるためにHaskell が設計される
- 1999: 安定化したバージョンHaskell98 が登場し一気に知名度が増す
理論的な背景だとチューリングマシンと同じぐらい古く、最初の関数型言語は2番目に古い高級言語です。
最近になって注目を集めている関数型プログラミングは、実はとっても古くからある概念だとわかりますね。
つまり、極めて古い歴史を持つため、その技術は洗練されているということです。
(まぁ実用的な実績はともかく研究はされていたということです。)