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 をくっつけていれば型安全だということか。ううむなんか不思議な感じがする。