レコード型

なんでOCamlのレコード型のフィールド名はみんな同じ空の下で管理されるんだろう。

# type a = { id : string; name : string };;
type a = { id : string; name : string; }
# type b = { id : string; value : int };;
type b = { id : string; value : int; }


(* idを持つtype bを宣言してしまったのでもうaとは会えない *)
# let foo = { id = "a01"; name = "foo" };;
Characters 10-38:
  let foo = { id = "a01"; name = "foo" };;
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: The record field label name belongs to the type a
       but is here mixed with labels of type b


# type c = { value : int; id : string };; (* 順番が違うだけのtype cさん *)
type c = { value : int; id : string; }
# let bar = { id = "a02"; value = 256 };; (* type bの順番で書いてもtype cに! *)
val bar : c = {value = 256; id = "a02"}

値に対してシンボル*1を束縛する・・・と考えると仕方ないような気もするけど、ちょっと使いにくそうなイメージがあるぷす。
まあそういうものだと思って受け入れることにしましょう。なんて広いこころ!


ちなみにC#の匿名型とは見た目しか似てない。

var a = new { ID = "a01" };
var b = new { ID = "a02", Value = 256 };
var c = new { Value = 512, ID = "a03" }; // 順番が入れ替わっただけでも別の型に!
Console.WriteLine( a.GetType() == b.GetType() ); //False
Console.WriteLine( b.GetType() == c.GetType() ); //False

*1:シンボルってLisp用語かな?笑