人気ブログランキング | 話題のタグを見る

Haskell の例外処理

ghci から存在しないファイルを読み出そうとすると、エラーメッセージが出る。

Prelude System.IO.Error> readFile "not_exist"
*** Exception: not_exist: openFile: does not exist (No such file or directory)

例外が発生しているわけだが、これをプログラムの中で捉えて例外処理をしてプログラムが止まってしまわないようにするためには catch 関数を使う。catch 関数の型は次のようになる。

Prelude> :t catch
catch :: IO a -> (IOError -> IO a) -> IO a

つまり、catch 関数は第1引数に IO a 型のデータをとり、第2引数に、「IOErro 型の引数をとり、戻り値が IO a 型の関数」をとる。そこで、実験をしてみた。

Prelude> catch (readFile "not_exist") (\e -> return "Exception")
"Exception"

IOError の情報を利用したいときは System.IO.Error をインポートする。すると IOError から文字列を取り出す関数 ioeGetErrorString を使うことができる。

Prelude System.IO.Error> catch (readFile "not_exist") (\e -> return $ ioeGetErrorString e)
"does not exist"

これは、冒頭のエラーメッセージにも使われていた。

ユーザー定義の IOError 型のデータを作るときは userError 関数を使う。

Prelude System.IO.Error> userError "user exception"
user error (user exception)

これを使って例外処理を発生させるには、ioError 関数を使う。

Prelude System.IO.Error> ioError $ userError "user exception"
*** Exception: user error (user exception)

同じことは fail 関数でも行える。

Prelude System.IO.Error> fail "user exception"
*** Exception: user error (user exception)

少しプログラムらしい使い方をしてみた。

Prelude System.IO.Error> catch (do putStrLn "in catch"; fail "now out") (\e -> return $ ioeGetErrorString e)
in catch
"now out"

参考サイト: あどけない話 Haskellでtry/throw/catch/finally
by tnomura9 | 2011-12-12 02:11 | Haskell | Comments(0)
<< 自前のエラーモナドの作り方。 『48時間でSchemeを書こ... >>