unsafePerformIO
unsafePerformIO は型安全でないらしい。
test :: IORef [a] test = unsafePerformIO $ newIORef [] main = do writeIORef test [42] bang <- readIORef test print (bang :: [Char])
は SEGV る。test が多相型になっているため、[Int] を書き込むこともできるし、 [Char] として読み出すこともできる。しかし、そんな操作は明らかに問題だ。
This problem with polymorphic references is well known in the ML community
とあるように ML においてはこの問題はよく知られていて、実際
let test = ref [] let _ = test := [42]; let bang = !test @ ["foo";"bar"] in print_endline (List.hd bang)
は型エラーとなる。test は多相型ではなく単相型になるから、test := [42] の時点で int list に型付けされる。そして次の !test @ ["foo";"bar"] は int list と string list の連結となりエラーとなる。
で、ML には value restriction があるから型安全だが、Haskell には無いので unsafePerformIO を使うと安全で無くなってしまうという話。
…じゃあ逆に言うと unsafePerformIO を使わず IO をくっつけていれば型安全だということか。ううむなんか不思議な感じがする。