packages feed

throwable-exceptions-0.1.0.7: example/Main.hs

{-# LANGUAGE TemplateHaskell #-}

-- | This is referenced from README.md
module Main where

import Control.Exception.Safe (throwM, MonadCatch, catch, SomeException)
import Control.Exception.Throwable (GeneralException(..), generalException, IndexOutOfBoundsException(..))
import Control.Exception.Throwable.TH (declareException)

{- !! These line is needed by declareException !! -}
import Control.Exception.Safe (Exception)
import Data.Typeable (Typeable)
{- ---------------------------------------------- -}


-- This is same as
--
-- data MyException a = MyException
--  { myExceptionCause :: String
--  , myExceptionClue  :: a
--  } deriving (Typeable)
--
-- instance Show a => Show (MyException a) where
--  ...
-- instance (Typeable a, Show a) => Exception (MyException a)
--
declareException "MyException" ["MyException"]
-- ^ the second argument (the list of String) will be made as a value constructor.

-- This is same as
--
-- data TwoException a =
--  FirstException
--    { firstExceptionCause :: String
--    , firstExceptionClue  :: a
--    } |
--  SecondException
--    { secondExceptionCause :: String
--    , secondExceptionClue  :: a
--    } deriving (Typeable)
--
-- instance Show a => (TwoException a) where
--  ...
-- instance (Typeable a, Show a) => Exception (TwoException a)
--
declareException "TwoException" ["FirstException", "SecondException"]


main :: IO ()
main = do
  print $ ([1..4] `at` 5 :: Either SomeException Int)
  print $ MyException "hi" 10
  print $ myException "poi"
  -- ^ a (fake) value constructor,
  -- this is same as `MyException` but without a clue value.
  print (foo :: Either SomeException Int)
  print $ FirstException "chino" 20
  print $ firstException "cocoa"
  print $ secondException "rize"
--
-- vvv  output result  vvv
--
-- Left IndexOutOfBoundsException: "index is too big"
-- MyException: "hi"
-- MyException: "poi"
-- Left FooException: poi poi poi !?


-- IndexOutOfBoundsException,
-- IOException',
-- IllegalArgumentException,
-- and GeneralException is presented by default.
at :: (MonadCatch m, Typeable a, Show a) => [a] -> Int -> m a
at xs index = do
  if index < length xs
    then return $ xs !! index
    else throwM $ IndexOutOfBoundsException "index is too big" (xs, index)
    --else throwM $ indexOutOfBoundsException' "index is too big"
    -- You can use above code without some clue


-- If you don't want to use TemplateHaskell (Control.Exception.Throwable.TH),
-- you can use GeneralException and generalException instead !
--
-- data GeneralException a = GeneralException
--   { exceptionName  :: String -- ^ This should be named by 'PascalCase' for show, for example: "MyOperation", "Database"
--   , exceptionCause :: String -- ^ The message for the cause of the exception
--   , exceptionClue  :: a      -- ^ The clue of the exception. This can be anything of Show instance
--   }
-- 
-- generalException :: String -> String -> GeneralException ()
-- generalException name cause = GeneralException name cause () 
--
foo :: (MonadCatch m, Typeable a, Show a) => m a
foo = throwM $ generalException "FooException" "poi poi poi !?"
-- This is same as `GeneralException "FooException" "poi poi poi !?" ()`