Standard MLファーストフードチュートリアル(1)-初識


Standard MLファーストフードチュートリアル(1)-初識
久しぶりにファーストフードのチュートリアルを書きましたが、関数式プログラミング言語に関する新しいシリーズを始めます.3つの言語を書くつもりです:Standard ML、ocamlとHaskell.これらの言語は新高ではありません.その中でStandard MLの知名度が最も低いかもしれません.MLシリーズの影響力のため、rustなどの新しい言語からこれらの古い言語の多くの知識を学んだことがあります.今はそれらを元に戻せばいいかもしれません.
実行環境
Standard MLは、その名の通り、ML言語の標準規範であり、主なバージョンはSML 90とSML 97である.標準的な実現には多くの方法がある.例えば,インタラクティブコンパイルを主な特徴とするSML/NJ,コンパイルの最適化を主な目標とするmlton.もう一つの重要なStandard MLコンパイラはケンブリッジ大学のDavid Matthewsが開発したpoly/MLであり,有名な推理証明ツールIsabelleがpolymlを用いて開発されたためである.
SML/NJは、ベルラボのDavid MacQueenとプリンストン大学のAndrew Appelが1986年に発起した.1997年のSMLの改訂を満たすため、1998年1月に110バージョンが発売された.2020年になると、メインバージョン番号は110です.例えば、私が今使っているバージョンはv 110です.97.
SML/NJのプロジェクトホームページは:http://www.smlnj.org/.そのソースコードはsvnを使用して管理されます.mltonとpolymlのソースコードはgithubで管理されています.mltonのアドレスは次のとおりです.https://github.com/MLton/mlton、ploymlのアドレスは:https://github.com/polyml/polyml/.
インストールすると、以上の3つの言語ツールが比較的汎用的で成熟したツールに属しているため、mac上のhomebrewやUbuntuなどの主流Linuxリリースバージョンでサポートされています.たとえばmacOSでは、homebrewを使用してインストールする3つの環境があります.
brew install mlton
brew install polyml
brew cask install smlnj

Ubuntuでは、次のコマンドを使用してインストールできます.
apt install smlnj
apt install mlton
apt install polyml

インストール後、smlコマンドを実行すると、sml/njのインタラクティブな環境に入ることができ、Standard MLコードの作成を学ぶことができます.「-」はsmlnjのプロンプトです.
Standard ML of New Jersey v110.79 [built: Sat Oct 26 12:27:04 2019]
-

ハローワールドプログラムの練習手を書いてもいいです.例えばhelloです.sml:
val a = 1 :int ;
print "Hello,World
";

smlnjはsml helloを通過することができる.smlが呼び出す.mlton helloを通ってもいいです.smlがコンパイルされ、helloが生成され、helloを実行すると実行結果が表示されます.
polycを使用してコンパイルすると、次のエラーが表示されます.
poly: : error: Value or constructor (main) has not been declared
Found near PolyML.export (List.nth (CommandLine.arguments (), 3), main)
Static Errors

これはpolymlにmain関数が必要だからです.main関数を書きましょう.
fun main() = print "Hello,World
";

次にpolycを呼び出してコンパイルします.
polyc hello2.sml -o hello2

最後にhello 2を実行すると、実行結果が表示されます.
polymlはpolyコマンドでインタラクティブに実行することもできます.
Poly/ML 5.8.1 Release

プロンプトは「>」です.
データ型
インタラクティブなインタフェースを使用して、基本的なデータ型の使い方を理解することができます.
数値タイプ
たとえば、整数1を入力します.
> 1;
val it = 1: int

このような整数はitというデフォルト変数に与えられ、そのタイプはintである.
-1はStandard MLで「~1」と表記されていますが、以下のようになります.
> val a = 0 - 1;
val a = ~1: int

符号点数はrealタイプです.
> val b = 1e8;
val b = 100000000.0: real

文字列
Standard MLは文字列タイプをサポートする:
> val d = "Hello";
val d = "Hello": string

ブール値
Standard MLはtrueとfalseの2つのキーワードを使用してboolタイプを表します.
> true;
val it = true: bool
> false;
val it = false: bool
> 1>0;
val it = true: bool

Null値
Standard MLの空のタイプはunitで、空のテーブル()を表すために使用されます.
> ();
val it = (): unit
> val g = ();
val g = (): unit

同様に、空の記録もunitです.
> val x3 = {};
val x3 = (): unit

文字の種類
「#」でcharタイプも記述できます.
> val e = #"c";
val e = #"c": char

ord関数は文字を整数に変換するために使用され、chrは逆にASCII値を文字に変換します.
> val x4 = ord(#"a");
val x4 = 97: int
> val x5 = chr(65);
val x5 = #"A": char

データ構造
メタグループ
タプルはカッコで記述されたリストです.タイプはいくつかのタイプの積になります.例えば(3.0,true)のタイプはreal*bool.
> val x6 = (3.0, true);
val x6 = (3.0, true): real * bool

リスト#リスト#
メタグループとは異なり、リストの要素は同じで、角カッコで表さなければなりません.空のリストはunitではなく、リストタイプです.
- val a1 = [];
val a1 = [] : 'a list

タイプが同じであれば、タプルでも問題ありません.
- val a2 = [1,2];
val a2 = [1,2] : int list
- val a3 = ["h","e"];
val a3 = ["h","e"] : string list
- val a4 = [(3,4),(2,5)];
val a4 = [(3,4),(2,5)] : (int * int) list

きろく
ハッシュ・テーブルと同様の構造で、keyとvalueを指定します.
- val a5 = {name="xulun",age=20};
val a5 = {age=20,name="xulun"} : {age:int, name:string}

数字1,2,3などをkeyとすると,確立された記録がメタグループである.例を見てみましょう
- val a7 = {1=true, 2=3.0};
val a7 = (true,3.0) : bool * real

マルチキャスト
Standard MLは、変数メタグループと値メタグループを使用するなど、モードマッチングマルチ付与をサポートしています.例を挙げるとわかります.
> val (x1,x2) = (1.0, true);
val x1 = 1.0: real
val x2 = true: bool

ステートメント
関数#カンスウ#
funで関数を定義することができます.平方を求める例を直接見てみましょう.
> fun s2 (x:int):int = x*x;
val s2 = fn: int -> int
> s2(4);
val it = 16: int

タイプを指定せずに、システムによって推定できます.
- fun add1 x y = x + y;
val add1 = fn : int -> int -> int

浮動小数点タイプを使用する場合は、システムによって推定される1つを指定できます.
- fun add2 (x:real) y = x + y;
val add2 = fn : real -> real -> real

コメント
Standard MLは(**)を使用してコメントを書きます.
じょうけんステートメント
Standard MLはif then else文をサポートし、ifが真であればthenの後の式を返し、そうでなければelseブランチの結果を返します.
- fun neg1 (x:int) : bool = if x < 0 then true else false;
val neg1 = fn : int -> bool

-1はsmlで~1と表示されていることを覚えています.上のif判断をテストします.
- neg1(1);
val it = false : bool
- neg1(~1);
val it = true : bool

ケース文
case文により,マルチブランチの条件を処理し,各条件を独自にマッチングすることができる.フォーマットはcase x of x 1=>something 1|x 2=>something 2|...
例を見てみましょう
- fun grade1(x:int) = case x of 0 => false | 1 => true | x => false;
val grade1 = fn : int -> bool
- grade1(1);
val it = true : bool
- grade1(0);
val it = false : bool
- grade1(100);
val it = false : bool

標準ライブラリ
標準言語としてStandard MLは移植可能な標準ライブラリもサポートしています.これらのライブラリを呼び出して、他の言語のように楽しくプログラミングすることができます.smlの標準ライブラリはBASISと呼ばれています.最初の呼び出しでbasisがロードされます.
- Char.isUpper(#"a");
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[library $SMLNJ-BASIS/(basis.cm):basis-common.cm is stable]
[autoloading done]
val it = false : bool

実数の絶対値を計算するなど、いくつかの例を示します.
- Real.abs(~1.5);
val it = 1.5 : real

整数回転数:
- val a10 = Real.fromInt(1);
val a10 = 1.0 : real

平方根を求める:
- val a11 = Math.sqrt(2.0);
[autoloading]
[autoloading done]
val a11 = 1.41421356237 : real

文字列接続:
- val a11 = String.concat(["Hello","World"]);
val a11 = "HelloWorld" : string

一緒に見るといいですね.タイプ、ブランチ、関数などがあります.強力なスタンダードライブラリもあります.おめでとうございます.Standard MLの世界で生きています.