ML (プログラミング言語)

ML（えむえる、Meta-Language）は、関数型言語のひとつである。現代風の関数型言語としては歴史が古いほうで、型推論機能などを持つが、デフォルトの評価戦略は遅延評価ではなく先行評価で、書き換えが可能なレコード型を持つなど、いわゆる「純粋関数型」でない特徴や機能を持つ。
概要.
自動定理証明系において、証明の道筋を関数として記述するためのメタ言語として生まれたという経緯を持ち（#歴史の節を参照）、名前はそのことに由来する。構文はISWIMの影響を受けている。
MLによってプログラマに知られるようになった機能に、型推論がある。これは、明示的に型の宣言を行わなくても、データの利用のされ方から、引数や関数の返す型を自動的に推論してくれる機能である。これにより、プログラマの負担が著しく軽減される。
標準（ないし一方言）としてStandard ML (SML) があり、その実装には、 (SML/NJ) や、東北大学電気通信研究所大堀研究室が開発を進めているSML#などがある。標準以外の仕様の実装としてはOCamlなどがある。詳細仕様は実装ごとに異なっており、各実装での仕様をそれぞれのMLの方言と捉える場合もある。
SMLの詳細とその実装の一覧はStandard MLを参照のこと。
言語仕様.
以降の記法や名前はSMLのものである。OCamlなどその他の実装については、SMLと差異があるため各実装の記事を参照のこと。
演算子.
MLの基本的な演算子は以下の通り
関数の定義.
MLの関数の定義は
 fun (関数名)(引数) = (内容);
と書く。Haskellと同様なパターンマッチングがある。複数のパターンはガード記法 | をセパレータとする。
例として階乗を求めるプログラムを以下に示す。
 fun factorial(1) = 1
 | factorial(n) = n * factorial(n-1);
MLでの関数の評価は関数が定義されたときに行われる。このためMLでは関数定義の順序が無視できない。例として
 fun a(x) = b(x-1) + x;
 fun b(x) = x * x;
のような関数がある場合は必ず b の方が先に定義されていないといけない。しかしこの場合はお互いを呼ぶような再帰呼び出しの実装が不可能である。そこでMLではそのような関数のために二つの関数を and でつなぐことによってこれを実装することができる。
例を挙げると
 fun take(nil) = nil
 | take(x::xs) = x::skip(xs)
 and skip(nil) = nil
 | skip(x::xs) = take(xs);
これは take が与えられたリストの奇数番目の要素を返し、skip が偶数番目の要素を返す関数である。
歴史.
デイナ・スコットの提案したPPLAMBDAという論理体系を利用し、ロビン・ミルナーは (LCF) という証明のチェックや定理の自動証明をするシステムを実装した。1973年に発足したEdinburgh LCFのプロジェクトにおいて、証明の道筋を関数として記述するためのメタ言語として開発されたのが、MLの最初であり、強い型付きの言語として設計された。
Edinburgh LCFとMLは、1975～76年にエディンバラ大学で実装された。特に1980年代以降、汎用プログラミング言語として多数の機能やライブラリが追加されている。
（この節 参考文献『新しいプログラミング・パラダイム』(ISBN 4-320-02493-1) pp. 120-121）