
#14349: Semigroup/Monoid instances for System.Exit.ExitCode -------------------------------------+------------------------------------- Reporter: neil.mayhew | Owner: (none) Type: feature request | Status: upstream Priority: low | Milestone: Component: libraries/base | Version: 8.2.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by neil.mayhew): Maybe it would help to mention my use case, which is running a set of regression tests implemented as shell commands. (They pipe the output of an executable into a `diff` against the expected output. The exit status of the shell command is that of the `diff`.) The program that runs the regression tests is then used as a Cabal test suite (of type `exitcode- stdio`). (A simplified version of) the code looks like this: {{{#!hs {-# OPTIONS_GHC -fno-warn-orphans #-} import Data.Monoid (Monoid(..)) import System.Process (system) import System.Exit (ExitCode(..), exitWith) instance Monoid ExitCode where mempty = ExitSuccess mappend ExitSuccess b = b mappend a _ = a data MyTest = MyTest String tests :: [MyTest] tests = map MyTest [ "echo Test1" , "echo Test2" , "exit 3" , "echo Test4" , "exit 5" ] main :: IO () main = mapM runTest tests >>= exitWith . mconcat runTest :: MyTest -> IO ExitCode runTest (MyTest cmd) = system cmd }}} To avoid the `Monoid` instance I could have the `runTest` function return a `Bool` instead, and use `and` to collect all the statuses: {{{#!hs main :: IO () main = mapM runTest tests >>= bool exitFailure exitSuccess . and runTest :: MyTest -> IO Bool runTest (MyTest cmd) = (==ExitSuccess) <$> system cmd }}} However, the `Monoid` approach is more elegant because it avoids the repeated and redundant use of machinery from `System.Exit`. In both cases, the exit code of the test suite is `3`. It also happens that the `diff` output appears in the output of the test suite, and all the tests are run, rather than stopping at the first failure. So the output of the simplified test suite above is: {{{ Test1 Test2 Test4 }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14349#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler