SML# - FeatureRecordPolymorphism Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

SML#は,[[多相型レコード計算の理論|http://www.pllab.riec.tohoku.ac.jp/~ohori/research/list.html#recordcalc]]
を基礎として,レコード多相性を完全にサポートする.
プログラマは,動的な名前サーチのオーバヘッドを気にすることなく,
特別のデータ構造の定義や関数などを用意することなく,
単に基本データ構造であるレコード操作を書くことによって,
レコード多相性を自由に使うことができる.

SML#では,レコードのフィールド取り出し演算子
#<label>
およびレコードパターン
{<label>=pattern,...}
を使用した関数に対しても,以下例のように,その最も一般的な型が推論される.
# fun f x = #name x;
val f = fn : ['a, 'b#{name:'a}. 'b -> 'a]
# f {name = "Joe", age = 21};
val it = "Joe" : string
fに対して推論された型情報
['a, 'b#{name:'a}. 'b -> 'a]
は,
この関数が,任意の型'aを値として持つ
nameフィールドを含む任意のレコードに適用可能な多相関数
であることを示している.
この中の'aは通常の型変数,
'b#{name:'a}
は'aの型を持つ"name"フィールドを含む任意のレコード型を表す.

このようにSML#では,特別な構文や演算を加えることなしに,
レコード多相性を完全にサポートしている.
したがって,プログラマは,従来要求された型宣言を省略するだけで,
レコードを含む任意の構造に対しても,MLの最大の特徴である
多相性を行かしたプログラムを書くことができる.

この基本機能に加え,SML#では,多相型レコード更新
のための以下の構文が用意されている.
  exp # {label1 = exp1, ..., labeln = expn}
この式の評価の結果,expで表されるレコードに
含まれる各ラベルlabeliの値をexniで表される
値に変更した新たなレコードが作成される.
例えば,ある特定のフィールドの値に1を加える関数は以下の
ような多相関数として定義できる.
# fun incX (x as {X,...}) = x # {X = X + 1};
val incX= fn : ['a#{X:int}.'a -> 'a]
# incX {X = 1, Y = 2};
val it = {X = 2, Y = 2} : {X:int, Y:int}
この構文は,従来のStandard MLの構文には現れないように選ばれているため,
この構文の追加によって,従来のプログラムがエラーになることはない.

さらにSML#コンパイラは,これら多相型レコード演算を,常に効率よい
整数オフセットによるロード演算にコンパイルする.
以下はコンパイルの実例である.
# fun makeGreeting {name= {first = "David", ...},...} = "Hi, Dave"
>   | makeGreeting {name = {last,...}, ...} =  "Dear Mr./Ms." ^ last;

  Record Compiled to:
  val makeGreeting =
    ['a#{name:'b},'b#{first:string, last:string}.
      fn {$175, $174, $173, $167} =>
        bind
          $170 = $167[$175]
        in
           bind
             $171 = $170[$174]
           in
              switch
                $171
              of "David" => "Hi, Dave"
               | _ =>
                   bind
                     last = $170[$173]
                   in
                     "Dear Mr./Ms." ^ last
                   end
           end
        end
    ]
makeGreeting関数は,レコード($167)と"name","first","last"の
それぞれのフィールドのオフセットを表す3つの整数引数($175,$174,$173)
を受け取る(複数引数)関数にコンパイルされている.
(これらコンパイルの中間結果は,smlsharpのスイッチを指定することによって,
実際にみることができる.)