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

Simon Peyton Jones simon.peytonjones at gmail.com
Wed Mar 27 09:53:06 UTC 2024


I think of it like this:

   - The core of the proposal is a way to map the value returned by `main`
   to an exit code.
   - The status quo is that it is always mapped to zero.
   - Your (2) continues with the status quo but adds a warning for return
   types other than () and Void.  Not worth doing in my view.
   - The type-class idea provides a general way to map the return value to
   an exit code.  Good plan.
   - I think we have to gate the extension, because currently a program
   with `main :: IO ExitCode` will always return exit code 0; but with the
   type-class thing it'll return the specified exit code.  A change in
   behaviour.
   - With no extension, but warning (*not *erroring), old programs (with
   say `main :: IO Bool`) may start to warn; that's OK.  It's easy to fix in a
   backward compatible way.  It's a bit like any other new warning.

Another possible plan, call it (4) in your list is: *if `main :: IO
ExitCode` then use that exit code. For all other types, return exit code 0*.
That is simpler than the type class story, but you don't list it as a
possibility.

My top picks are:

   - (4) just make main :: IO ExitCode special
   - (1c) Type class form, gated by an extension, with warning for
   non-instance types
   - Without the extension, today's behaviour (000000);
      - with the extension, warn if the return type is no an instance
      (TTWTWT).

Sadly, neither of these is in your list,, but those are the two that seem
plausible to me.

I feel we should be involving Shea, and indeed the wider community.  If a
bunch of actual users had strong opinions, I would immediately withdraw
mine. I don't feel strongly.

Simon

On Tue, 26 Mar 2024 at 15:24, Arnaud Spiwack <arnaud.spiwack at tweag.io>
wrote:

> Of course I'll ask Shea, but I want to gather thoughts first. Hence my
> call for a vote. If I may make a final attempt at defining the options I
> layed out. If it doesn't work, I'll change my strategy.
>
> Legend:
> - 0: main exits with exit code 0 (success)
> - E: type error
> - W: a warning is emitted
> - T: the `ExitStatus` type class is used to select the exit code. (On Void
> and (), T and 0 are the same thing)
> - N: not available under this alternative
>
> Your examples:
> module Ex1 where {  ..; main :: IO Void }
> module Ex2 where {  ..; main :: IO () }
> module Ex3 where {  ..; main :: IO Int }
> module Ex4 where { ...; main :: IO ExitCode }   -- ExitCode exists already
> module Ex5 where { ...; main :: IO Bool }         -- No ExitStatus
> instance for Bool
> module Ex6 where { ...; data T = ..; main :: IO T; instance ExitStatus T
> where ... }
>
> Alternatives:
> 1a. TT0T0T (this is Shea's preferred proposal)
> 1b. -XNoWombat: 000000 / -XWombat TTETET
> 2. 00WWWN
> 3a. -XNoWombat: 00WWWW / -XWombat: TTETET
> 3b. -XNoWombat: 00WWWW / -XWombat: TTWTWT
>
> On Tue, 26 Mar 2024 at 12:57, Simon Peyton Jones <
> simon.peytonjones at gmail.com> wrote:
>
>> I'm sorry Arnaud, but my brain is insufficiently large to accommodate the
>> implications of five different briefly specified options.   Would you (or
>> Shea) like to specify them more precisely, perhaps on GH since email
>> threads are harder to follow (and it allows others to contribute).  I think
>> it would help to give some examples to illustrate the consequences of each.
>>
>> Here's the kind of thing I mean (below).
>>
>> Also can we check with Shea that he is content with these options?  It's
>> his proposal
>>
>> Simon
>>
>>
>> module Ex1 where {  ..; main :: IO Void }
>> module Ex2 where {  ..; main :: IO () }
>> module Ex3 where {  ..; main :: IO Int }
>> module Ex4 where { ...; main :: IO ExitCode }   -- ExitCode exists already
>> module Ex5 where { ...; main :: IO Bool }         -- No ExitStatus
>> instance for Bool
>> module Ex6 where { ...; data T = ..; main :: IO T; instance ExitStatus T
>> where ... }
>>
>> *Option 1: a warning when main isn't at type IO () or IO Void*
>>
>>    - A warning on Ex3-6.
>>    - Ex4 returns exit code 0
>>    - Is this warning on by default?  Can it be suppressed?  (Rather than
>>    provide -Wnoxxx flag, we could just say "change the code to return ()"
>>
>> *Option 2: New type-class-based behaviour without extension *
>>
>>    - Ex1,2,4.6 work fine
>>    - Ex4 returns the specified exit code.
>>    - Ex3, and Ex5 yields "no instance for ExitStatus Int" (and Bool resp)
>>
>> *Option 2a: Like Option 2 but with warning*
>>
>>    - Ex3 and Ex5 yield a warning not at error; but run fine
>>
>>
>> *Option 3: New type-class-based behaviour with extension *
>>
>>    - Without -XWombat: like Option 1
>>    - With -XWombat: like Option
>>
>> *Option 3a: Like Option 3 but with warning*
>>
>>    - With -XWombat, Ex3 and Ex5 yield a warning not at error; but run
>>    fine
>>
>>
>> On Tue, 26 Mar 2024 at 09:35, Arnaud Spiwack <arnaud.spiwack at tweag.io>
>> wrote:
>>
>>> Alright, so here are the plausible alternatives
>>>
>>> 1a. New type-class-based behaviour without extension
>>> 1b. New type-class-based behaviour gated by an extension
>>> 2. Just a warning (when main isn't at type IO () or IO Void)
>>> 3a. A warning + the new type-class-based behaviour gated by an
>>> extension. With the extension, types that don't implement the type class
>>> raise an error.
>>> 3b. A warning + the new type-class-based behaviour gated by an
>>> extension. With the extension, types that don't implement the type class
>>> raise a warning (which could have a different phrasing than without the
>>> extension).
>>>
>>> Let's vote!
>>>
>>> On Fri, 22 Mar 2024 at 15:30, Malte Ott <malte.ott at maralorn.de> wrote:
>>>
>>>> On 2024-03-22 08:58, Arnaud Spiwack wrote:
>>>> > @Malte, in my opinion, with the extension on, types which are not
>>>> covered
>>>> > by the type class should error out.
>>>>
>>>> Ah, I see. Well, I am fine either way.
>>>>
>>>> I just don’t see much value in deciding for the user which code
>>>> problems are
>>>> unacceptable. Especially since this will make the corresponding language
>>>> extension more breaking and thus harder to make the default.
>>>> Others have voiced similar opinions in the GitHub thread.
>>>>
>>>> Best
>>>> Malte
>>>> _______________________________________________
>>>> 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
>>>
>>
>
> --
> 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/20240327/c9854948/attachment-0001.html>


More information about the ghc-steering-committee mailing list