Hanzo.hs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. {-# LANGUAGE FlexibleInstances #-}
  2. {-# LANGUAGE ScopedTypeVariables #-}
  3. module Hanzo
  4. ( Mainable(..)
  5. , Termination(..)
  6. , Exit.ExitCode(..)
  7. ) where
  8. import qualified Control.Exception as Exn
  9. import qualified Control.Monad.Trans.Except as Except
  10. import qualified System.Environment as Env
  11. import qualified System.Exit as Exit
  12. import qualified System.IO as IO
  13. -- | The 'Mainable' class represents computations which can be
  14. -- encapsulated as the 'main' function of a program.
  15. class Mainable k where
  16. main :: k -> IO ()
  17. guardExceptions :: IO a -> IO a
  18. guardExceptions action = do
  19. result <- Exn.try action
  20. case result of
  21. Left (e :: Exn.SomeException) -> do
  22. IO.hPutStrLn IO.stderr (Exn.displayException e)
  23. Exit.exitWith (Exit.ExitFailure 1)
  24. Right x -> pure x
  25. instance Termination r => Mainable (IO r) where
  26. main action = do
  27. r <- guardExceptions action
  28. code <- report r
  29. Exit.exitWith code
  30. instance Termination r => Mainable (Except.ExceptT String IO r) where
  31. main action = do
  32. exn <- guardExceptions (Except.runExceptT action)
  33. case exn of
  34. Left err -> do
  35. IO.hPutStrLn IO.stderr err
  36. Exit.exitWith (Exit.ExitFailure 1)
  37. Right r -> do
  38. code <- report r
  39. Exit.exitWith code
  40. instance Mainable k => Mainable ([String] -> k) where
  41. main action = do
  42. args <- Env.getArgs
  43. let rest = action args
  44. main rest
  45. -- | The 'Termination' class represents values which can be returned
  46. -- from a 'Main' function which might represent success or failure.
  47. class Termination t where
  48. report :: t -> IO Exit.ExitCode
  49. instance Termination () where
  50. report _ = pure Exit.ExitSuccess
  51. instance Termination Bool where
  52. report True = pure Exit.ExitSuccess
  53. report False = pure (Exit.ExitFailure 1)
  54. instance Termination Exit.ExitCode where
  55. report x = pure x
  56. instance Show e => Termination (Either e ()) where
  57. report (Left err) = do
  58. IO.hPutStrLn IO.stderr (show err)
  59. pure (Exit.ExitFailure 1)
  60. report (Right ()) =
  61. pure Exit.ExitSuccess
  62. instance Termination (Maybe ()) where
  63. report Nothing = pure (Exit.ExitFailure 1)
  64. report (Just ()) =
  65. pure Exit.ExitSuccess