pureいじってみる

先日、id:nskj77 さんに教えてもらった、Pureという言語を試してみた。

簡単に、pureの特徴を説明すると、

なんというか、いろんなものを詰め込んだ感がいなめませんね。

msiのパッケージや、macportにも入っているので、インストールは簡単。
どんな感じかだけ見たいなら、examples/hello.pureを見れば、Haskellとか、MLを知っているならわかると思います。


で、いじってみた感想なのですが、まず置き換えモデルが面白すぎ。pureは、式を変換できるところまで、置き換えていきます。
squ x = x*x;という関数に対して、プリミティブな値である8をいれると計算してくれます。

> squ x = x * x;
> squ 8;
64

しかし、定義されていない(a+b)という値を与えると、(a+b)*(a+b)というふうに置き換えてくれます。

> squ (a+b);
(a+b)*(a+b)

そのあと、別の置き換え方法を定義してやり、再度(a+b)をsquにわたしてやると、さらに置き換え可能なところまで置き換えてくれます。

> (x + y) * z = x*z +y*z;
> x *(y+z) = x*y + x*z;
> x*(y*z)=(x*y)*z;
> x+(y+z)=(x+y)+z;
> squ (a+b);
a*a+a*b+b*a+b*b

面白いとは思うんだけど、何が便利なの?っていわれると困ります。まだ、いじり足りていないので。あと、置き換えパターンの定義をミスると、置き換えで無限ループ起こして大変なことになります。(C-cとかC-dでインタラプトもできませんでした。強制的にkillしたった。)


あとパターンマッチと動的片付けの部分について。pureは、関数定義時に引数の型を指定できます。

> append1 x::int = x + 1;
> append1 10;
11

このとき、引数に定義されていない型の値を渡すと、当然置き換えができません。

> append1 "10";
append1 "10"

なので、stringのときの定義を作ってやれば、動きを変更できます。

> append1 x::string = x + "1";
> append1 "10";
"101"

当然、引数に型を定義しなくても、処理で使われる演算が型に対して定義されていれば、当然計算されます。

> append x = x + x;
> append 10;
20
> append "mo";
"momo"

ここらへんは、Haskellとかだと型推論や総称型で似たような動きできるけど、いちいち総称型作らなくていいのは便利そうね。
ただ、動的だからリストにいろんな型をいれれるのは、ちょっと怖いかなぁ。

> map (\x->x+x) [1,"10",3];
[2,"1010",6]


あと、curry化が用意にできるのは、萌えるなぁ。

> map (+) [1,"10",3];
[(+) 1,(+) "10",(+) 3] /* (+) は2引数必要な演算なのでcurry化されるのみ */
> map (\x-> x 1) (map (+) [1,"10",3]);
[2,"10"+1,4] /* 文字列に数字は適用できないから置き換えるのみ */

あと、flipあるでよ。

> (+) "ho" "ge";
"hoge"
> flip (+) "ho" "ge";
"geho"

今のところ、一番の難関はセミコロンの付け忘れです。