[ghc-steering-committee] Proposal #631: Set program exit code by main return type, recommendation: accept something

Richard Eisenberg reisenberg at janestreet.com
Mon Mar 4 19:24:06 UTC 2024


I left out a key part of my last email -- apologies. I'm floating a
counter-proposal where we *require* an instance of ExitStatus on the return
type of `main`, with a transition period. In contrast, my understanding of
the proposal written is that it would use such an instance if it exists,
but issue a warning if it doesn't, in perpetuity.

Richard

On Mon, Mar 4, 2024 at 6:14 AM Simon Peyton Jones <
simon.peytonjones at gmail.com> wrote:

> I am a little worried about breaking programs that end in an
> innocent-looking `return 0`, just because some other languages like to end
> programs with that phrase
>
>
> The proposal specifies that such a program returns `ExitSuccess`, but adds
> a warning. That seems OK to me; it does not break the program.
>
> Oh -- maybe you mean that `return 1` means "return with exit code 1"
> today.  Is that really true?  I don't think so.
>
> Overall this proposal seems fine to me.  I'd be happy to see it done.
>
> Simon
>
> On Thu, 29 Feb 2024 at 12:38, Richard Eisenberg <reisenberg at janestreet.com>
> wrote:
>
>> I haven't followed this proposal closely. But couldn't we have a
>> transition period toward this eventual goal? That is, introduce a new
>> warning, on by default, if `main` returns anything other than `()`. That
>> goes for a few releases. Then we require that the return type of main has
>> an instance of ExitStatus.
>>
>> I'm not worried about changing the behavior of programs that have type IO
>> ExitCode but expect the program to return 0 unconditionally; that's just
>> begging for confusion. I am a little worried about breaking programs that
>> end in an innocent-looking `return 0`, just because some other languages
>> like to end programs with that phrase. So I'm not sure if we should have an
>> instance ExitStatus Int (or instance ExitStatus Integer) -- but we probably
>> should. If a program ends with `return 1`, the programmer probably wants
>> the OS to return 1 as well.
>>
>> Richard
>>
>> On Thu, Feb 29, 2024 at 5:29 AM Arnaud Spiwack <arnaud.spiwack at tweag.io>
>> wrote:
>>
>>> Dear all,
>>>
>>> Shea Levy proposes to do something with the values returned by `main`
>>> https://github.com/ghc-proposals/ghc-proposals/pull/631 .
>>>
>>> The problem is that `main` is allowed to be of type `IO A` for any `A`.
>>> And GHC will simply drop the value returned by `main`. Shea contends that
>>> it's surprising. I agree that dropping a value without the compiler being
>>> explicitly instructed to is surprising. But Shea says that when `A` is
>>> `ExitCode` this is even more surprising. Namely `main :: IO ExitCode; main
>>> = return $ Failure 1` actually terminates with exit code 0. And I doubt
>>> that it's what anybody expects when reading the code.
>>>
>>> The proposal is simple, but I have a lot of comments on it. Sorry about
>>> that…
>>>
>>> Now, this sort of proposal is tricky. When the current behaviour is
>>> confusing, we want to change the default. But putting the new default
>>> behind an extension doesn't really solve the fact that there's a trap. The
>>> extension is, therefore, unlikely to be well tested before it becomes part
>>> of the next language edition.
>>>
>>> Shea's main proposition doesn't actually use an extension though. He
>>> adds a type class `ExitStatus`, and if `ExistStatus A`, then `main :: IO A`
>>> uses the instance to determine the exit code based on the return value.
>>>
>>> The only change to the current behaviour is that `main :: IO ExitCode`
>>> instead of always terminating with exit code 0 when returning now
>>> terminates with the expected error code. The argument for not putting this
>>> behind an extension is that virtually anybody affected by the change will
>>> actually have the behaviour they were expecting. But maybe the argument
>>> isn't strong enough (the changes may be more “interesting” if some library
>>> exports some `ExistStatus` instance).
>>>
>>> This design of this proposal is inspired by Rust's design. I've asked
>>> our Rust team, and they certainly seem to have internalised the idea of
>>> returning an exit code. It really seems a pretty natural feature to have.
>>> So I'm rather in favour of some flavour of the type class implementation.
>>> Though have a look at the alternatives, where you'll find other approaches
>>> such as restricting the type of `main` to unsurprising types.
>>>
>>> One caveat with respect to the main proposal: it is proposed that when
>>> no `ExistStatus A` is found, then we drop the returned value like today. I
>>> don't know that it's quite easy to implement this behaviour. But it can be
>>> recovered by a catch-all overlapping instance, so maybe it's a better way
>>> to specify the desired behaviour.
>>>
>>> --
>>> Arnaud Spiwack
>>> Director, Research at https://moduscreate.com and https://tweag.io.
>>> _______________________________________________
>>> ghc-steering-committee mailing list
>>> ghc-steering-committee at haskell.org
>>> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
>>>
>> _______________________________________________
>> ghc-steering-committee mailing list
>> ghc-steering-committee at haskell.org
>> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-steering-committee/attachments/20240304/886d3912/attachment.html>


More information about the ghc-steering-committee mailing list