| パラダイム | マルチパラダイム:機能的、汎用的、命令的 |
|---|---|
| デザイン: | ロビン・ミルナー、エディンバラ大学の他の人たち |
| 初登場 | 1973年 |
| タイピングの規律 | 推測、静的、強い |
| 方言 | |
| OCaml、標準ML、F# | |
| 影響を受けた | |
| イスイム | |
| 影響を受けた | |
| Clojure、Coq、Cyclone、C++、Elm、F#、F*、Haskell、Idris、Kotlin、Miranda、Nemerle、OCaml、Opa、Erlang、Rust、Scala、標準 ML | |
ML (メタ言語) は、汎用の高水準関数型プログラミング言語です。多態的な Hindley–Milner 型システムを使用していることで知られており、明示的な型注釈 (型推論)を必要とせずにほとんどの式のデータ型を自動的に割り当て、型の安全性を保証します。適切に型指定された ML プログラムは実行時型エラーを引き起こさないことが正式に証明されています。 [1] ML は、関数の引数、ガベージコレクション、命令型プログラミング、値渡し、カリー化のパターンマッチングを提供します。汎用プログラミング言語である一方、 ML はプログラミング言語の研究で頻繁に使用されており、形式意味論を使用して完全に仕様化および検証される数少ない言語の 1 つです。その型とパターンマッチングにより、コンパイラの作成、自動定理証明、形式検証など、他の形式言語での操作に適しており、一般的に使用されています。
概要
MLの特徴には、値渡し評価戦略、第一級関数、ガベージコレクションによる自動メモリ管理、パラメトリック多態性、静的型付け、型推論、代数的データ型、パターンマッチング、例外処理などがあります。MLは静的スコープ規則を使用します。[2]
MLは、関数型プログラミングを推奨しているものの、副作用[3]を許容しているため、不純な関数型言語と呼ばれることもあります( Lispなどの言語と同様ですが、Haskellなどの純粋関数型言語とは異なります)。ほとんどのプログラミング言語と同様に、MLは積極的評価を使用します。つまり、すべての部分式が常に評価されますが、クロージャを使用することで遅延評価を実現できます。したがって、Haskellと同様に無限ストリームを作成して使用できますが、その表現は間接的です。
ML の強みは主に言語設計と操作 (コンパイラ、アナライザー、定理証明器) に適用されますが、バイオインフォマティクスや金融システムでも使用される汎用言語です。
MLは1970年代初頭にエディンバラ大学でロビン・ミルナーらによって開発され、[4]その構文はISWIMに触発されています。歴史的には、MLはLCF定理証明器(その言語pplambdaは一階述語計算と単純型付き多態的ラムダ計算の組み合わせであり、そのメタ言語としてMLを持っていました)の証明戦術を開発するために考案されました。
現在、 ML ファミリーにはいくつかの言語があり、その中でも最も有名なのはStandard ML (SML)、OCaml、F#の3つです。 MLのアイデアは、Haskell、Cyclone、Nemerle、[5] ATS、Elmなど、他の多くの言語に影響を与えています。[6]
例
次の例では、標準 ML の構文を使用しています。OCaml や F# などの他の ML 方言では、若干異なります。
階乗
楽しい fac ( 0 : int ) : int = 1
| fac ( n : int ) : int = n * fac ( n - 1 )
これは、階乗を単一の終了基本ケースを持つ再帰関数として記述します。これは、数学の教科書に記載されている階乗の説明に似ています。ML コードの多くは、機能と構文の点で数学に似ています。
示されている定義の一部はオプションであり、この関数の型を説明しています。表記 E : t は、式E が型 t を持つと読み取ることができます。たとえば、引数 n には整数型(int) が割り当てられ、整数 n に fac を適用した結果である fac (n : int) も整数型になります。関数 fac 全体の型は、関数から整数への関数(int -> int) になります。つまり、 fac は引数として整数を受け入れ、整数の結果を返します。型推論のおかげで、型注釈は省略でき、コンパイラによって導出されます。型注釈なしで書き直すと、例は次のようになります。
楽しい ファク 0 = 1
| fac n = n * fac ( n - 1 )
この関数は、ML プログラミングの重要な部分であるパターン マッチングにも依存しています。関数のパラメータは必ずしも括弧で囲む必要はなく、スペースで区切る必要があることに注意してください。関数の引数が 0 (ゼロ) の場合、整数 1 (一) を返します。その他の場合は、2 行目が試されます。これは再帰であり、基本ケースに達するまで関数を再度実行します。
この階乗関数の実装は、負の引数によって再帰呼び出しの無限下降チェーンが発生するため、終了することが保証されません。より堅牢な実装では、次のように再帰する前に非負の引数をチェックします。
fun fact n = let
fun fac 0 = 1
| fac n = n * fac ( n - 1 )
in
if ( n < 0 ) then raise Domain else fac n
end
問題のあるケース (n が負の場合) は、ML の例外システムの使用を示しています。
この関数は、内部ループを末尾呼び出しとして記述することでさらに改善することができ、呼び出しスタックが関数呼び出しの数に比例して増加しなくて済むようになります。これは、内部関数にアキュムレータという追加のパラメータを追加することで実現されます。最終的に、次のようになります。
fun fact n = let
fun fac 0 acc = acc
| fac n acc = fac ( n - 1 ) ( n * acc )
in
if ( n < 0 ) then raise Domain else fac n 1
end
リスト逆順
次の関数は、リスト内の要素を 逆順にします。より正確には、指定されたリストと比較して要素が逆の順序になっている新しいリストを返します。
楽しい 逆 [] = []
| 逆 ( x :: xs ) = (逆 xs ) @ [ x ]
この逆の実装は正しくて明確ですが、非効率的で、実行に2 乗の時間が必要です。関数は線形時間で実行するように書き直すことができます。
fun 'a 逆 xs : 'a list = List . foldl ( op :: ) [] xs
この関数は、パラメトリック多態性の例です。つまり、任意の型の要素を持つリストを消費し、同じ型のリストを返すことができます。
モジュール
モジュールは、大規模なプロジェクトやライブラリを構造化するための ML のシステムです。モジュールは、署名ファイルと 1 つ以上の構造ファイルで構成されます。署名ファイルは、実装するAPI (C ヘッダー ファイルやJava インターフェイスファイルなど) を指定します。構造は、署名を実装します (C ソース ファイルや Java クラス ファイルなど)。たとえば、次のコードでは、算術署名と、有理数を使用したその実装を定義します。
署名 ARITH =
sig
type t
val zero : t
val succ : t -> t
val sum : t * t -> t
end
構造 Rational : ARITH =
struct
datatype t = Rat of int * int
val zero = Rat ( 0 , 1 )
fun succ ( Rat ( a , b )) = Rat ( a + b , b )
fun sum ( Rat ( a , b ), Rat ( c , d )) = Rat ( a * d + c * b , b * d )
end
これらは、「use」コマンドによってインタープリターにインポートされます。実装とのやり取りは、シグネチャ関数を介してのみ許可されます。たとえば、このコードを介して「Rat」データ オブジェクトを直接作成することはできません。「structure」ブロックは、実装の詳細をすべて外部から隠します。
ML の標準ライブラリは、このようにモジュールとして実装されています。
参照
- 標準MLと標準ML § 実装
- 依存型ML : 依存型MLの拡張
- ATS : 依存型MLのさらなる発展
- Lazy ML : 1980 年代初頭の実験的な遅延評価 ML 方言
- PAL(プログラミング言語):MLに関連する教育用言語
- OCaml : Coqやさまざまなソフトウェアを実装するために使用されるML方言
- F# : .NETフレームワーク向けのオープンソースのクロスプラットフォーム関数型言語
参考文献
- ^ ロビン・ミルナー。プログラミングにおける型多態性の理論。コンピュータとシステム科学ジャーナル、17(3):348–375、1978年。
- ^ ミルナー、ロビン、トフテ、マッズ (1991)。「4.1 コンテキスト、環境、スコープ」。標準 ML に関する解説。MIT プレス。pp. 35–36。ISBN 0-262-63137-7。
- ^ Sebesta, Robert (1999).プログラミング言語の概念(第 4 版). Addison-Westley. p. 54. ISBN 0-201-38596-1。
- ^ Gordon, Michael JC (1996). 「LCF から HOL まで: 短い歴史」2007 年 10 月 11 日閲覧。
- ^ 開発者の「特殊部隊」のためのプログラミング言語、ロシアソフトウェア開発ネットワーク:ネメルレプロジェクトチーム、 2021年1月24日閲覧
- ^ Tate, Bruce A.; Daoud, Fred; Dees, Ian; Moffitt, Jack (2014). 「3. Elm」。7 週間で 7 つの言語を学ぶ(書籍版: P1.0-2014 年 11 月版)。 The Pragmatic Programmers, LLC。 pp. 97、101。ISBN 978-1-941222-15-7101 ページで、
Elm の作成者である Evan Czaplicki は次のように述べています。「私は、これらすべての言語の共通の歴史を理解するために、「Elm は ML ファミリーの言語です」と言う傾向があります。」[「これらの言語」とは、Haskell、OCaml、SML、および F# を指します。]
さらに読む
- 標準 ML の定義、Robin Milner、Mads Tofte、Robert Harper、MIT Press 1990 年、(改訂版では著者 David MacQueen を追加)、MIT Press 1997 年、ISBN 0-262-63181-4標準 ML の定義 (改訂版)。
- 「Standard ML の解説」、「Robin Milner」、「Mads Tofte」、MIT Press 1997、ISBN 0-262-63137-7。
- ML for the Working Programmer、Lawrence Paulson、Cambridge University Press 1991、1996、ISBN 0-521-57050-6。
- Harper, Robert (2011). 標準 ML でのプログラミング(PDF)。カーネギーメロン大学。
- MLプログラミングの要素、Jeffrey D. Ullman、Prentice-Hall 1994、1998、ISBN 0-13-790387-1。
外部リンク
- ニュージャージー州の標準ML、もう一つの人気のある実装
- F#、Microsoft .NET フレームワークを使用した ML 実装。2010-02-18 にWayback Machineでアーカイブされました。
- プログラム全体を最適化する標準MLコンパイラー MLton
- CakeML は、正式に検証されたランタイムとアセンブラへの変換機能を備えた ML の読み取り評価印刷ループ バージョンです。
