(relaxed) value restriction を回避する pure magic

よいこは読んではいけません。Obj.magic の話です。

よいこは寝てください。

、、、

、、、

、、、

はい、悪い子しかいませんね。じゃあ、Obj.magic の話をしましょう。

Obj.magic は関数なので、適用された結果は expansive です。なので、結果が polymorphic に出来ませんでした:

# (Obj.magic 0 : ('a -> 'a) option);;
- : ('_a -> '_a) option = None

ほんとは ('a -> 'a) option にしたいのに、、、関数じゃないからエータ変換もできない。
OCaml の型システムで遊ぶときって、無理矢理 monomorphic なモノを polymorphic にしたかったりするんですが、Obj.magic で折角型を無理矢理変えても無理なのでした。

それをボヤいていたら惹玖が良い方法を見つけてくれたよ。(代わりに私は variance のバグを見つけてあげました):

# let x = Obj.magic 0
x : 'a = <poly>
# let x : ('a -> 'a) option = x;;
x : ('a -> 'a) option = None

一度 'a という型にするのがミソ。こうすると、OCaml の relaxed value restriction のおかげで ∀a.a というキモい polymorphic な型になります!! ここからはどんな polymorphic な型にも instance できるので、型制限すればおk。

俺の書いた関数は pure だから、絶対 polymorphic にしても安全なのに、OCaml の型システムが polymorphic にしてくれない! とお嘆きのあなたは、この「pure magic」テクニックで無理矢理 polymorphic にしてしまいましょう。

ああ、もちろん、何が起こっても知らないよ。