(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 にしてしまいましょう。
ああ、もちろん、何が起こっても知らないよ。