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

**URL:** <https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687>\
**Category:** Uncategorized\
**Created:** [January 31, 2024, 1:40pm UTC](https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687 "2024-01-31T13:40:09Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![shlevy](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/shlevy/32/4062_2.png) [@shlevy](https://discourse.haskell.org/u/shlevy)\
**Post date:** [January 31, 2024, 1:40pm UTC](https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687/1 "2024-01-31T13:40:09Z")

</div>

Hi all,

I have written a simple [proposal](https://github.com/ghc-proposals/ghc-proposals/pull/631) that would allow for the value yielded by `main` to set the program’s exit status, in a well-typed way. The committee has requested more feedback from users, if you have an opinion on this either way (especially if you’re a new user or are frequently involved in teaching Haskell) your feedback would be appreciated!

From the motivation section:

> Many languages, perhaps most notably C, allow specifying a program’s exit  
> code by returning an appropriate value from main. Haskell98 does  
> allow a main which yields values of any type, but surprisingly it does not  
> do anything with the result: any successful execution will result in a successful  
> program exit, even if main yields 1 or `ExitFailure 1`.
> 
> Before this proposal, the following program would exit with code 0 even  
> when there are no results:
> 
> ```haskell
> main :: IO ExitCode
> main = do
> results <- doSomeWork
> case results of
> [] -> pure (ExitFailure 1)
> _ -> print results >> pure ExitSuccess
> 
> ```
> 
> With this proposal in place, the program would exit with code 1 in that  
> case.
> 
> This proposal follows Rust in using a typeclass for return types which can signal exit codes.
> 
> This is a minor quality of life improvement, but one that I’ve seen hit  
> newcomers now and then and matches reasonable expectations of program  
> behavior.

---

<div class="post-metadata">

**Author:** ![haanss](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/haanss/32/3690_2.png) [@haanss](https://discourse.haskell.org/u/haanss)\
**Post date:** [January 31, 2024, 3:33pm UTC](https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687/2 "2024-01-31T15:33:36Z")

</div>

Looking at it this proposal it feels so non-controversial I’m surprised they’d want more feedback. Consider me\* a +1.

\*I am a student, though I would no longer classify myself as a _new user_, for what its worth…

---

<div class="post-metadata">

**Author:** ![BurningWitness](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/burningwitness/32/3665_2.png) [@BurningWitness](https://discourse.haskell.org/u/BurningWitness)\
**Post date:** [January 31, 2024, 3:52pm UTC](https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687/3 "2024-01-31T15:52:43Z")

</div>

While I sympathize with the idea of properly returning a value instead of carrying it through an exception, it feels like this deserves a language extension, not a typeclass.

Then if GHC ever decides to do a cleanup and write a whole new standard that extension could simply be promoted to a default behavior.

---

<div class="post-metadata">

**Author:** ![atravers](https://avatars.discourse-cdn.com/v4/letter/a/45deac/32.png) [@atravers](https://discourse.haskell.org/u/atravers)\
**Post date:** [January 31, 2024, 3:53pm UTC](https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687/4 "2024-01-31T15:53:33Z")

</div>

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

```haskell
{-# 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:

```haskell
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?](http://discourse.haskell.org/t/using-unsafeperformio-safely/4146)

- 

> [@](#):
>
> [jaror:](http://discourse.haskell.org/t/using-unsafeperformio-safely/4146/9)
> 
> In the pure subset of Haskell throwing an exception is like entering an infinite loop. Exceptions thrown from within the unsafely performed IO are no different.

- 

> [@](#):
>
> [VictorCMiraldo:](http://discourse.haskell.org/t/using-unsafeperformio-safely/4146/14)
> 
> Memory can also run out making allocation in `bytestring` fail too…

- 

> [@](#):
>
> [VictorCMiraldo:](http://discourse.haskell.org/t/using-unsafeperformio-safely/4146/20)
> 
> […] if the code crashes, it would also have crashed had we placed `IO` everywhere anyway.

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`:

```haskell
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` .

---

<div class="post-metadata">

**Author:** ![Vlix](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/vlix/32/1551_2.png) [@Vlix](https://discourse.haskell.org/u/Vlix)\
**Post date:** [January 31, 2024, 4:15pm UTC](https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687/5 "2024-01-31T16:15:15Z")

</div>

While I would have maybe preferred that Haskell’s `main` function had always been `IO Int`, making it into `IO ExitCode` seems a bit of a hassle in regards to backwards compatibility, and having a type class that changes the `a` in `main :: IO a` into an `ExitCode` seems like a lot of unnecessary abstractions.

I really feel like this would be a good idea, had we not been in the situation we are in right now.

To be honest, forcing `main` to be of type `IO Void` actually feels like a good option to me, so that any exiting is explicit. This way, people new to making a (Haskell) executable also get confronted with the concept of “exiting a program” and the choices that need to/can be made. 🤔  
Downside is, it breaks all executable source code out there 😅

---

<div class="post-metadata">

**Author:** ![TeofilC](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/teofilc/32/3987_2.png) [@TeofilC](https://discourse.haskell.org/u/TeofilC)\
**Post date:** [January 31, 2024, 8:27pm UTC](https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687/6 "2024-01-31T20:27:08Z")

</div>

I think an important aspect of `return` in other languages is that they allow early return from a function. Haskell’s `return` is a false friend in this way.

So even if this proposal was accepted, new users would still be confused by `return ExitSuccess >> print "Foo"` printing `"Foo"`. And we should still be recommending `exitWith` instead

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [January 31, 2024, 8:46pm UTC](https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687/7 "2024-01-31T20:46:42Z")

</div>

I’m curious what happens in GHCJS (and any other flavour of Haskell that compiles to JS). Does it even have `main`? Can it terminate? Does it have an “exit code”?

---

<div class="post-metadata">

**Author:** ![sclv](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/sclv/32/71_2.png) [@sclv](https://discourse.haskell.org/u/sclv)\
**Post date:** [January 31, 2024, 8:49pm UTC](https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687/8 "2024-01-31T20:49:24Z")

</div>

I think something like the proposal would have been maybe a little cleaner from the start.

That said, the current situation is largely fine, and I think it would cause more confusion and churn to try to alter things at this point, since this goes straight to the spec of the Haskell language.

Personally, I very rarely write programs that need to signal explicit failure with an exit code – and when I do, the existing mechanism of throwing is far cleaner and more straightforward to me – i.e. I’d never want to explicitly return such a code anyway, since my exits will come rather deeply nested, regardless.

---

<div class="post-metadata">

**Author:** ![atravers](https://avatars.discourse-cdn.com/v4/letter/a/45deac/32.png) [@atravers](https://discourse.haskell.org/u/atravers)\
**Post date:** [January 31, 2024, 9:09pm UTC](https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687/9 "2024-01-31T21:09:45Z")

</div>

> [@tomjaguarpaw](#):
>
> I’m curious what happens in GHCJS (and any other flavour of Haskell that compiles to JS).

…particularly considering that JS apparently has no notion of a `main` symbol:

`https://stackoverflow.com/questions/9015836/why-doesnt-javascript-need-a-main-function`

* * *

> [@TeofilC](#):
>
> Haskell’s `return` is a false friend […]

Have people ever found `do` in Haskell confusing because `do` in other languages can indicate the start of a loop (and then went looking for [`while`](https://hoogle.haskell.org/?hoogle=while) in Haskell)? I think abstract monadic I/O would have confused more new Haskellers than `return` being a overloaded method.

But `return` is being deprecated in favour of `pure`, though:

```haskell
taint :: ... => a -> m a

```

probably would have been a better replacement.

---

<div class="post-metadata">

**Author:** ![BurningWitness](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/burningwitness/32/3665_2.png) [@BurningWitness](https://discourse.haskell.org/u/BurningWitness)\
**Post date:** [February 1, 2024, 4:02am UTC](https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687/10 "2024-02-01T04:02:30Z")

</div>

> [@sclv](#):
>
> the existing mechanism of throwing is far cleaner and more straightforward

I don’t know if I’d call it straightforward, my assumption would be that every current program is effectively

```haskell
mainWithExit :: IO ExitCode
mainWithExit = ExitSuccess <$ main

```

The meaningful question here is whether the user should have the ability to return this code directly when they’re at the very end of the program.

---

<div class="post-metadata">

**Author:** ![JakobBruenker](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jakobbruenker/32/1615_2.png) [@JakobBruenker](https://discourse.haskell.org/u/JakobBruenker)\
**Post date:** [February 1, 2024, 3:09pm UTC](https://discourse.haskell.org/t/feedback-requested-simple-proposal-to-set-program-exit-code-by-mains-value/8687/11 "2024-02-01T15:09:38Z")

</div>

If we use `IO Void`, what would be the exit code of `main = pure undefined`? This currently exits successfully with code 0.
