Feedback requested: Simple proposal to set program exit code by main's value

For some time now I’ve been contemplating a generalisation of main:

{-# LANGUAGE Haskell2010 #-}
import Foreign.Marshal  -- see page 269 of 329 in the H. 2010 Report

class Mainly a where
    mainly :: a -> r

instance Mainly (IO a) where
    mainly act = unsafeLocalState (act >> exitSuccess)
                  -- or e.g. primMainlyIO :: IO a -> r 

With a suitable instance, any value can be “returned” by main :: Mainly a => a e.g:

instance Mainly ExitCode where
    mainly ecd = mainly (exitWith ecd)

instance Mainly Int where
    mainly n = mainly (ExitFailure n)  -- ...but also see page 299 of the Report

instance Mainly Bool where
    mainly b = mainly (if b then 0 else 1)

instance Mainly () where
    mainly () = mainly (pure ())

              ⋮ 

From Using unsafePerformIO safely?

The presence of Mainly.mainly (or something like it) could help to bring more clarity to such matters. For example, if throw could be defined using throwIO:

throw e = mainly (throwIO e)

then if mainly m = ⊥ for all m :: IO a (as intended), throw e would also equal , the result of an infinite regression or loop: let y = y in y. Similarly, if m :: IO a was going to end the program in some other way, then so would mainly m :: r .

1 Like