プログラミング言語SML#解説 4.0.0版
8 SML#の拡張機能:レコード多相性

8.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.41421356237, 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.41421356237 : real
# myPPoint distance;
val it = 1.41421356237 : real

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