unsafePerformIO を使って IO を外す

■ Haskell 再入門Haskell(前編)に unsafePerformIO を使って IO を外す例がありましたので写経してみました。

import System.IO.Unsafe

configFileName =  "config.txt"

loadConfig :: IO (String,Integer)
loadConfig = 
  readFile configFileName >>= 
  \dat -> let [server, portNumber] = lines dat
          in return (server, read portNumber)

server     :: String
portNumber :: Integer
(server,portNumber) = unsafePerformIO loadConfig


main = do
   (s,p) <- loadConfig
   putStrLn $ "server:" ++ s ++ " portNumber:" ++ show p

   putStrLn $ "server:" ++ server ++ " portNumber:" ++ show portNumber

(server,portNumber) = unsafePerformIO loadConfig によって server と portNumber はグローバル変数のようにいちいち (s,p) <- loadConfig をやらなくても読み出せます。

unsafePerformIO :: IO a -> a 

「あ〜良かった。これで便利だ」と思っていると unsafePerformIO で検索すると安易に使ってはならないと言う記事が見つかりました。

unsafePerformIO は Foreign Function Interface (FFI) のために必要になったのであって、IO を外すために作られたわけじゃないんだ。グローバル変数が欲しくなったら、Data.IORefを使えと言ってます。