SMLによる関数型言語入門 #2
Standard MLで関数型言語に入門します。
参考サイト
M.Hiroi's Home Page / Functional Programming
Standard ML について - ウォークスルー Standard 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のおもしろい部分、というか関数型プログラミングのおもしろい部分にはここでは触れられていないので随時続きの記事を書いていきますー。
それでは