[ghc-steering-committee] Proposal #631: Set program exit code by main return type, recommendation: accept something
Adam Gundry
adam at well-typed.com
Thu Mar 7 09:26:55 UTC 2024
I've added a comment to the GitHub thread
(https://github.com/ghc-proposals/ghc-proposals/pull/631#issuecomment-1983060484)
elaborating slightly on Richard's suggestion (albeit with an effectively
indefinite transition period).
Adam
On 05/03/2024 08:52, Arnaud Spiwack wrote:
> 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 <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 <mailto: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 <mailto: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
> <mailto: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
> <mailto: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
> <mailto: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 <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
> <https://moduscreate.com> and https://tweag.io
> <https://tweag.io>.
--
Adam Gundry, Haskell Consultant
Well-Typed LLP, https://www.well-typed.com/
Registered in England & Wales, OC335890
27 Old Gloucester Street, London WC1N 3AX, England
More information about the ghc-steering-committee
mailing list