読者です 読者をやめる 読者になる 読者になる

SMLによる関数型言語入門 #2

SML 関数型言語

Standard ML関数型言語に入門します。

参考サイト

M.Hiroi's Home Page / Functional Programming

Standard ML について - ウォークスルー Standard ML

ML

SML/NJインストール。

SML/NJとは対話型のコンパイラです。

Macだとbrewでインストールできたので、これが便利だと思います。 

$ brew install smlnj

$ smlで対話型インタプリタが起動して,$ sml fileとすればプログラムを読み込んでからインタプリタを起動できます.

SML入門

SMLは関数型言語であるとともに、強力な型推論機能をもちなおかつ強い静的片付け言語であることが大きな特徴になっている。

まず最初に、コメントは以下のように挿入できる。

(* comment *)

組(tuple)

smlにおいてtupleは非常に重要な概念。関数のところでも出てくるのでチェック。

smlではtupleを使って、新しい型を定義する。これは他の言語の配列のようなものとはまた一味違った感じがして面白い。

tupleでは複数の異なった型のデータを用いて新しい型を作ることができる。例えば以下。

- val tuple = (1,"test");
val tuple = (1,"test") : int * string

これによって新たに、int * string型の変数tupleが定義された、というわけだ。

tupleにはtuple(これって自分で定義した型だ!)を入れることもできる。例えば以下の2つではtupleの型は異なるものになってしまう。

- val a = ((1, 2), 3);
val a = ((1,2),3) : (int * int) * int
- val b = (1, (2, 3));
val b = (1,(2,3)) : int * (int * int)

要素を取り出すためには#数字(tuple)を使う。そしてsmlのtupleでは左側の要素から1,2,...と続いていく。

- #1(a);
val it = (1,2) : int * int
- #2(a);
val it = 3 : int
- #1(b);
val it = 1 : int
- #2(b);
val it = (2,3) : int * int

リスト

SMLにおいて値をプログラムの途中で書き換えることができるのは、参照と、配列だけ。

SMLリストの宣言は以下のように。

- a;
val it = [1,2,3,4] : int list

リストは関数 hd, tl を使って要素を取り出すことができる。

- hd( a );
val it = 1 : int
- tl( a );
val it = [2,3,4] : int list

tlみたいに最初以外すべて取り出すのは、なんか新鮮。

演算子 :: (コンス演算子) で、リストの先頭に要素を追加(合成)することができる。左側に要素、そして右側はリストでないといけないので注意。(nilを使うこともできる。nilについては後で説明します。)

- val e = 0 :: a;
val e = [0,1,2,3,4] : int list

また演算子 @ でリスト同士を連結できる。

- val f = [1,2,3] @ [4,5,6];
val f = [1,2,3,4,5,6] : int list

空リストは[]となり、これはnilとしても使える。ということは、nilとはリストであるということでもある。

なるほど、SML、型にすごく厳しい印象を受ける。

関数

そしてついにきた関数の使い方。

定義は以下のようにする。

- fun 関数名 args =;

関数名のあとに常に括弧をつけておいてもいいけど、実はこれを基本系と覚えた方がsmlへの理解が捗るように思う。その理由は後述。

以下は引数を2倍する関数times2()の例。

- fun times2 x  = x * 2;
val times2 = fn : int -> int
- times2( 4 );
val it = 8 : int

関数型言語では、関数もデータ型のひとつになる。この考え方は非常に重要で、fun で指定した名前が times2 であれば、smlはtimes2という変数をつくり、変数 times2 の値は関数型のデータになるということ。

上の例の2行目からも分かるように、fn型のデータtimes2の方は、int -> int = 引数 -> 返り値というふうに扱われるわけだ。なるほどー面白い。

複数の引数を取る場合はsmlではtupleを使う。以下のように宣言できる。

- fun 関数名 (args, ...) =;

あれ、なんか他の言語の普通の関数宣言じゃん!でもスペース空いてるし!ってなるんだけど、実はこれ、宣言した関数の引数としてtupleを渡している、という構造になっているだけなのだ。

smlでは引数をひとつしかとれないので、こうしてtupleを引数として渡すことでそれを実現している。

関数の中で使われてるxとかyって、変数じゃん!って思う。

これは局所変数と呼ばれる。Cとかでもあるね。スコープがきいてその関数内でしか使えないから、副作用を気にする必要がないということかな。(最もこの関数内での副作用はさけることができないと思うけど)

ということで

ということでSMLの基礎部分をさらってみました。

といってもまだStandar MLのおもしろい部分、というか関数型プログラミングのおもしろい部分にはここでは触れられていないので随時続きの記事を書いていきますー。

それでは