Standard ML について

1. Standard ML とは

Standard ML(SML)は代表的な関数型言語の一つです. プログラミング言語 ML の標準仕様または一方言という位置づけにあたります. 同じ ML 言語族の言語としては OCaml が有名です(最近 F# も仲間に加わりました).

ML は,1970 年代にエジンバラ大学で,定理証明支援系 Edinburgh LCF のためのメタ言語(metalanguage)として設計された経緯があります. これが ML という名前の由来です. そして後に,ML の標準仕様という位置づけで Standard ML が定められました. LISP にとっての Common Lisp みたいな存在ということになります.

2. Standard ML の特徴

Standard ML は次のような特徴を持つ言語です.

  • 関数型プログラミング言語

  • 強力な型システム

  • パターンマッチング機構

  • 高度なモジュールシステム

  • 命令型言語的な機能

2.1. 関数型プログラミング言語

関数型プログラミング言語(functional programming language)または単に "関数型言語" とは,"関数" によってプログラムを構成するプログラミングスタイルを基本とする言語のことです. ML のほかに,LISP や Haskell が代表的な関数型言語として有名です.

ここでいう 関数(function)とは,いわゆる数学の関数と同じく,同じ引数に対して同じ値を返すプログラム部品 のことをいいます. 例えば,$f(1)$ という式の値がある時点で 5 と評価され,別のある時点(例えば 1 秒後)に 7 と評価されるなら,$f$ はここでいう関数ではありません.

関数と関数もどき

関数がプログラムの主役となる関数型言語では,関数は 第一級オブジェクト(first-class object)です. ここで,第一級オブジェクトとは,変数に格納したり,関数の引数や返り値に使ったりできるデータのことをいいます.

ML なら,リスト [1, 2, 3, 4, 5] の要素を 2 乗する処理を,関数式を使って次のように簡単に書くことができます. (以下に示すコードは,ハイフンで始まる 1 行目が対話環境への入力で,2 行目が対話環境の出力です.)

- map (fn x => x * x) [1, 2, 3, 4, 5];;
val it = [1,4,9,16,25] : int list

2.2. 強力な型システム

ML の特筆すべき特徴は,なんといってもその強力な型システムにあります. ML の型システムは強い静的型付けであり,たいへん強力な型推論機構を備えていることで有名です.

- fun area_of_circle r = Math.pi * r * r;
val area_of_circle = fn : real -> real

この例では,円の面積を求める関数 area_of_circle を宣言しています. この関数の宣言には型を何も明示していませんが,ML のコンパイラは area_of_circle の型を real -> real と自動的に推論し,推論された型に基づいて静的な型検査を行います.

この例はかなり単純な例でしたが,ML の型推論機構は多相型(パラメータ化された型)の推論など,たいへん高度な推論にも対応しています.

ML で初めて採用されたこの型推論機構は,Hindley–Milner 型推論機構 として知られています. この型推論機構は後発の言語に多大な影響を与えており,Haskell や Rust など多くの言語が Hindley–Milner ベースの型システムを採用しています.

2.3. パターンマッチング機構

強力なパターンマッチング機構も,ML の特徴的な言語機能の一つです. ML では,表現力の高いパターンマッチング機構が,条件分岐の記述に関して中心的な役割を渡します.

- fun length nil     = 0              (* 引数が空リストの場合 *)
=   | length (x::xs) = 1 + length xs  (* 引数が非空リストの場合 *) ;;
val length = fn : 'a list -> int

この例は,リストの長さを求める関数 length を,パターンマッチングを利用して定義したものです. ML では,多くの関数の定義はこのようにパターンマッチングを利用して記述します.

2.4. 命令型言語的な機能

ML は関数型言語ではありますが,参照型(再代入可能な変数を実現するデータ型)や例外処理機構といった,命令型言語の機能も提供しています. 現実のプログラムでは副作用を伴う処理がしばしば必要となるため,こうした命令型言語の機能はたいへん有用です.

なお,このような命令型言語の機能が参照透過性を損なうことから,ML は純粋な関数型言語ではありません.

"同じ式はどのタイミングで評価しても同じ値になる" という性質を,参照等価性(referential transparency)といいます.

2.5. 高度なモジュールシステム

Standard ML には,大規模なプログラムを適当な構成単位で分割して管理するためのモジュールシステムが用意されています. ML におけるモジュールシステムは,以下の 3 要素から構成されているという点で特徴的です.

  • ストラクチャ(structure): いわゆる一般的なモジュール

  • シグネチャ(signature): ストラクチャの仕様を記述したもの

  • ファンクタ(functor): ストラクチャを生成する関数

ファンクタはパラメータ化されたモジュールを実現し,シグネチャはモジュールの外部仕様を定義します.

3. Standard ML の仕様

Standard ML の公式な仕様は,1990 年と 1997 年に書籍として出版されています.

  • R. Milner, M. Tofte, and R. Harper. The Definition of Standard ML. MIT Press, 1990.

  • R. Milner, M. Tofte, R. Harper, and D. MacQueen. The Definition of Standard ML (Revised). MIT Press, 1997.

以前図書館で借りて読んだことがありますが,大部分が推論規則の羅列になっていて,初学者が読めるような代物ではありませんでした. 両者とも本と同じ内容のPDFが下記のページで公開されていますので,興味のある方は読んでみてはいかがでしょうか.