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

Arnaud Spiwack arnaud.spiwack at tweag.io
Tue Mar 5 08:52:51 UTC 2024


This is Alternative 7.5 in the current version of the proposal
https://github.com/shlevy/ghc-proposals/blob/io-exitcode/proposals/0631-main-return-types.rst#75require-an-exitstatus-instance
.

PS: I tend to agree with Richard that requiring an ExitStatus instance is
the preferable option. But food for thought for the proposal thread when
that conversation happens there: should that be gated behind an extension?
In which case it won't become the default before the next language edition.

/Arnaud

On Mon, 4 Mar 2024 at 21:35, Simon Peyton Jones <simon.peytonjones at gmail.com>
wrote:

> 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.
>
>
> Ah  I had not realised that.
>
> But why?
>
> Rather than answer here (private to SC) why don't you put your proposal on
> the discussion thread, say why, and invite feedback.
>
> Simon
>
>
> On Mon, 4 Mar 2024 at 19:24, Richard Eisenberg <reisenberg at janestreet.com>
> wrote:
>
>> 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
>>>>
>>>

-- 
Arnaud Spiwack
Director, Research at https://moduscreate.com and https://tweag.io.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-steering-committee/attachments/20240305/0078e522/attachment.html>


More information about the ghc-steering-committee mailing list