Ch.4 SML#の拡張機能:レコード多相性

§ 4.7. 多相バリアントの表現

レコード構造は,各要素に名前を付けたデータ構造です. この構造の双対をなす概念にラベル付きバリアントがあります. 多くの方にとって不慣れな概念と思われますが,必要とされる機能はレ コードとほぼ同一であるため,多相レコードが表現できれば,多相バリアントも 表現できます. 多相バリアントに興味のある方への参考に,以下,その考え方とコード 例を簡単に紹介します.

レコードが名前付きのデータの集合であるのに対して,ラベル付きバリ アントは,名前付きの処理の集合の下での処理要求ラベルのついたデータと考え ることができます. 直行座標系と極座標系の両方のデータを扱いたい場合を考えます. それぞれのデータは処理の仕方がちがいますから,データにどちらの座 標系かを表すタグ(名前)を付けます. これらデータを多相関数と一緒に使用できるようにする機構が多相バリ アントです. これは,バリアントタグを,メソッド集合から適当なメソッドを選び出 すセレクタと考えると,多相レコードを使って表現できます. 同一の点の2つのそれぞれの座標系での表現は,例えば以下のようにコー ド可能です.

# val myCPoint = fn M => #CPoint M {X=1.0, Y = 1.0};
val myCPoint = fn : ['a#{CPoint: {X: real, Y: real} -> 'b}, 'b. 'a -> 'b]
# val myPPoint = fn M => #PPoint M {r=1.41421356, theta = 45.0 };
val myPPoint = fn : ['a#{PPoint: {r: real, theta: real} -> 'b}, 'b. 'a -> 'b]

つまりタグTをもつバリアントは,タグTを処理するメソッドスイー トを受け取り,自分自身にその処理を呼び出す行うオブジェクトと表現します. あとは,必要な処理をそれぞれの表現に応じて書き,タグに応じた名前 をもつレコードにすればよいわけです. 例えば,原点からの距離を計算するメソッドは以下のように実現できます.

val distance =
{
     CPoint = fn x,y,... => Real.Math.sqrt (x *x + y* y),
     PPoint = fn r, theta,... => r
};

多相バリアントデータをメソッドスイートに適用することによって起動できます.

# myCPoint distance ;
val it = 1.41421356 : real
# myPPoint distance ;
val it = 1.41421356 : real

これによって,表現の異なるデータのリストなどを多相関数によって安 全に処理できるようになります.