IT練習ノート

IT関連で調べたこと(実際は嵌ったこと)を書いています。

Haskellで例外処理の初歩

import System.Environment (getArgs)
import Control.Exception (catch, SomeException)

main :: IO ()
main = do
  args <- getArgs
  out <- catch (readFile $ head args ) (\_ -> return "error")
  print out
test$ runghc test02.hs test02.hs1

test02.hs:17:10:
    No instance for (GHC.Exception.Exception e0)
      arising from a use of `catch'
    The type variable `e0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance GHC.Exception.Exception GHC.Exception.ArithException
        -- Defined in `GHC.Exception'
      instance GHC.Exception.Exception GHC.Exception.ErrorCall
        -- Defined in `GHC.Exception'
      instance GHC.Exception.Exception SomeException
        -- Defined in `GHC.Exception'
      ...plus 7 others
    In a stmt of a 'do' block:
      out <- catch (readFile $ head args) (\ _ -> return "error")
    In the expression:
      do { args <- getArgs;
           out <- catch (readFile $ head args) (\ _ -> return "error");
           print out }
    In an equation for `main':
        main
          = do { args <- getArgs;
                 out <- catch (readFile $ head args) (\ _ -> return "error");
                 print out }

参考 stackoverflow.com

型が曖昧ということらしい。 catchの型を確認してみる。

Prelude> :t Control.Exception.catch
Control.Exception.catch
  :: GHC.Exception.Exception e => IO a -> (e -> IO a) -> IO a

型を明示した関数を用意してみる

import System.Environment (getArgs)
import Control.Exception (catch, SomeException)

notifyError :: SomeException -> IO String
notifyError _ = return "error"

main :: IO ()
main = do
  args <- getArgs
  out <- catch (readFile $ head args ) notifyError
  print out
~           
# エラー系
test$ runghc test02.hs test02.hs1
"error"
# 正常系
test$ runghc test02.hs test02.hs
"import System.Environment (getArgs)\nimport Control.Exception (catch, SomeException)\n\nnotifyError :: SomeException -> IO String\nnotifyError _ = return \"error\"\n\nmain :: IO ()\nmain = do\n  args <- getArgs\n--  file <- readFile ( head args )\n--  print file\n--  print $ readFile ( head args ) \n--  readFile ( head args ) >>= (\\x -> print x)\n--  out <- catch (readFile $ head args ) (\\e -> print e::SomeException >> return \"\" ) \n--  out <- catch (readFile $ head args ) (\\(e::SomeException) ->return \"\") \n--  out <- catch (readFile $ head args ) (\\err -> print (err::SomeException) >> return \"\") \n--  out <- catch (readFile $ head args ) (\\_ -> return \"error\") \n  out <- catch (readFile $ head args ) notifyError \n  print out\n"
(root)MacBook-Air:test ogawanaoto$