SML#でオーバーローディング!


SMLでは、型システムがオーバーロードをうまく扱えないため、基本的にオーバーロード不可能なのですが、
トップレベルに公開されている一部の数値演算(関数)は特別扱いで、オーバーロードされています。(OCamlではこの特別扱いを撤廃してるのが特徴的です。)


これがあると、数値同士の足し算やかけ算が書きやすくなります。

- 5.0 + 6.2;
val it = 11.2 : real
- 100 + 256;
val it = 356 : int


SML#ではこれをユーザランドで定義出来るらしいと風の噂を聞きつけたので

さっそく使ってみました。

(* to_string.smi *)
_require "basis.smi"

val to_str =
	case 'a in 'a -> string of
         int  => Int.toString
       | real => Real.toString
       | word => Word.toString
	   (* ここで関数定義は書けないみたい *)

(* to_string.sml *)
(* からっぽ *)

smiに書く必要があるみたいです。なのでその場でラムダ式とか書けません。
別モジュールのインターフェースとして見えているシンボルに振り分けるだけ…といった感じでしょうか。


呼び出す側

(* main.smi *)
_require "basis.smi"
_require "to_string.smi"

(* main.sml *)
val _ = app print [to_str 314, "\n", to_str 1.24, "\n", to_str 0x15, "\n"];

オーバーロードされた文字列化関数が定義出来ました!!

実行します

~/work/smlsharp $ smlsharp.exe -c to_string.sml
~/work/smlsharp $ smlsharp.exe main.sml
~/work/smlsharp $ ./a.out
314
1.24
21

ちゃんと型に応じて適切な関数が呼ばれていますね!


ホントはこんな感じに書けるといいんですが…。どこまで出来るんだろうか。

fun g_to_str x =
  case x of NONE => "NONE"
          | SOME v => g_to_str v