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

Simon Peyton Jones simon.peytonjones at gmail.com
Fri Mar 22 09:03:43 UTC 2024


I'd like to have some more understanding of what's feasible to implement.
Adam, Simon PJ, could you share some insight there?


I don't think any of the alternatives discussed here are hard to implement.

Simon

On Fri, 22 Mar 2024 at 07:59, Arnaud Spiwack <arnaud.spiwack at tweag.io>
wrote:

> @Malte, in my opinion, with the extension on, types which are not covered
> by the type class should error out.
>
> I'd like to have some more understanding of what's feasible to implement.
> Adam, Simon PJ, could you share some insight there?
>
> On Thu, 21 Mar 2024 at 00:19, Malte Ott <malte.ott at maralorn.de> wrote:
>
>> On 2024-03-19 15:15, Arnaud Spiwack wrote:
>> > So, my opinion that I promised, is that the best would probably be to
>> have
>> > add a warning when main doesn't have type `IO ()` or `IO Void` without
>> the
>> > extension (the behaviour is otherwise unchanged), and then change the
>> > behaviour to use the typeclass with an extension (which we hope to turn
>> on
>> > by default in the next language edition). The extension should probably
>> >
>> > Now, I don't actually know how to implement this properly. So maybe
>> it's a
>> > bad idea. But I believe that's what I'd like to see.
>> > disable the warning.
>>
>> From my understanding that is basically equivalent to what I was
>> proposing.
>> It has the properties:
>>
>> * Using a return type which could reasonably be expected to exit with
>> failure
>>   should warn on -Wdefault (no matter whether a potential extension is
>> enabled).
>>   * Concretely this means any return type but (), Void and maybe forall
>> a. a, when the extension is off.
>>     * The warning could point to existing instances and the extension.
>>   * For anything which does not have an ExitCode implementation, when the
>> extension is on.
>> * Using the ExitCode type class should be possible but gated behind an
>> extension.
>>
>> Now the question whether we should have two different warnings, one when
>> the
>> extension is on and one when it is off or one warning which changes its
>> wording
>> and behavior slightly depending on the extension being enabled does not
>> matter
>> that much in my opinion.
>>
>> Best
>> Malte
>>
>> > On Fri, 15 Mar 2024 at 15:32, Matthías Páll Gissurarson <mpg at mpg.is>
>> wrote:
>> >
>> > > I agree. I like it, but better behind an extension to avoid surprises
>> and
>> > > enable experimentation.
>> > >
>> > > On Fri, 15 Mar 2024 at 13:15, Simon Marlow <marlowsd at gmail.com>
>> wrote:
>> > >
>> > >> I also think any change in behaviour should be behind an extension.
>> > >>
>> > >> Cheers
>> > >> Simon
>> > >>
>> > >> On Thu, 14 Mar 2024 at 16:51, Simon Peyton Jones <
>> > >> simon.peytonjones at gmail.com> wrote:
>> > >>
>> > >>> I like the proposal basically as is. i.e. typeclass + warning
>> > >>> Especially the fact that it warns everyone and breaks no-one (who
>> > >>> doesn’t want
>> > >>> to).
>> > >>>
>> > >>> I am weakly in favor of gating the usage of the typeclass for
>> anything
>> > >>> but ()
>> > >>> and Void behind an extension. That way no program will newly exit
>> with
>> > >>> failure
>> > >>> without the user opting in and we might be able to experiment more
>> on
>> > >>> the type
>> > >>> class.
>> > >>>
>> > >>>
>> > >>> I'm with Malte.   But I don't have strongly held views.
>> > >>>
>> > >>> Simon
>> > >>>
>> > >>> On Thu, 14 Mar 2024 at 14:04, Malte Ott <malte.ott at maralorn.de>
>> wrote:
>> > >>>
>> > >>>> I like the proposal basically as is. i.e. typeclass + warning
>> > >>>> Especially the fact that it warns everyone and breaks no-one (who
>> > >>>> doesn’t want
>> > >>>> to).
>> > >>>>
>> > >>>> I am weakly in favor of gating the usage of the typeclass for
>> anything
>> > >>>> but ()
>> > >>>> and Void behind an extension. That way no program will newly exit
>> with
>> > >>>> failure
>> > >>>> without the user opting in and we might be able to experiment more
>> on
>> > >>>> the type
>> > >>>> class.
>> > >>>>
>> > >>>> Best
>> > >>>> Malte
>> > >>>>
>> > >>>> On 2024-03-14 14:32, Arnaud Spiwack wrote:
>> > >>>> > Dear all,
>> > >>>> >
>> > >>>> > Shea has updated his proposal based on the committee's feedback.
>> > >>>> >
>> > >>>> > There seem to be two main alternatives being considered at the
>> moment
>> > >>>> > - Having a type class to compute the exit code based on the type.
>> > >>>> This is
>> > >>>> > Shea's favourite. It can be done without an extension (as Shea's
>> > >>>> proposing)
>> > >>>> > or with an extension.
>> > >>>> > - Keep the current behaviour but emit a warning when the return
>> type
>> > >>>> of
>> > >>>> > `main` isn't `()` or `Void`.
>> > >>>> >
>> > >>>> > I have opinions about my preference, but I'd like to hear about
>> > >>>> everybody's
>> > >>>> > thoughts first.
>> > >>>> >
>> > >>>> > On Thu, 7 Mar 2024 at 10:27, Adam Gundry <adam at well-typed.com>
>> wrote:
>> > >>>> >
>> > >>>> > > 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
>> > >>>> > >
>> > >>>> > > _______________________________________________
>> > >>>> > > 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.
>> > >>>>
>> > >>>> > _______________________________________________
>> > >>>> > 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
>> > >>>>
>> > >>> _______________________________________________
>> > >>> 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
>> > >>
>> > >
>> > >
>> > > --
>> > > --  Matthías Páll Gissurarson <http://mpg.is/>
>> > > _______________________________________________
>> > > 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.
>>
>> > _______________________________________________
>> > 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.
> _______________________________________________
> 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/20240322/1ff3a817/attachment-0001.html>


More information about the ghc-steering-committee mailing list