Proposal #631: Set program exit code by main return type, recommendation: accept something

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.

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
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@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

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
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
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@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

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@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
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
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@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

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
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@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@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
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@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

This is Alternative 7.5 in the current version of the proposal
https://github.com/shlevy/ghc-proposals/blob/io-exitcode/proposals/0631-main...
.
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
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
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@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@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
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@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@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.

I've added a comment to the GitHub thread (https://github.com/ghc-proposals/ghc-proposals/pull/631#issuecomment-1983060...) 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... https://github.com/shlevy/ghc-proposals/blob/io-exitcode/proposals/0631-main... .
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
mailto:simon.peytonjones@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
mailto:reisenberg@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
mailto:simon.peytonjones@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
mailto:reisenberg@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
mailto:arnaud.spiwack@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

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
I've added a comment to the GitHub thread ( https://github.com/ghc-proposals/ghc-proposals/pull/631#issuecomment-1983060...)
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... < 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
mailto:simon.peytonjones@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
mailto:reisenberg@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
mailto:simon.peytonjones@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
mailto:reisenberg@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
mailto:arnaud.spiwack@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@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.

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
wrote: I've added a comment to the GitHub thread ( https://github.com/ghc-proposals/ghc-proposals/pull/631#issuecomment-1983060...)
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... < 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
mailto:simon.peytonjones@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
mailto:reisenberg@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
mailto:simon.peytonjones@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
mailto:reisenberg@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
mailto:arnaud.spiwack@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@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@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

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
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
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
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
wrote: I've added a comment to the GitHub thread (
https://github.com/ghc-proposals/ghc-proposals/pull/631#issuecomment-1983060... )
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...
<
https://github.com/shlevy/ghc-proposals/blob/io-exitcode/proposals/0631-main...
.
PS: I tend to agree with Richard that requiring an ExitStatus
instance
is the preferable option. But food for thought for the proposal
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
mailto:simon.peytonjones@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
mailto:reisenberg@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
mailto:simon.peytonjones@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
mailto:reisenberg@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
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
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
mailto:arnaud.spiwack@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
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
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,
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
On 2024-03-14 14:32, Arnaud Spiwack wrote: proposing) thread programs programs there's the then 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@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@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

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@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
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
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
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
wrote: I've added a comment to the GitHub thread (
https://github.com/ghc-proposals/ghc-proposals/pull/631#issuecomment-1983060... )
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...
<
https://github.com/shlevy/ghc-proposals/blob/io-exitcode/proposals/0631-main...
.
PS: I tend to agree with Richard that requiring an ExitStatus
instance
is the preferable option. But food for thought for the proposal
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
mailto:simon.peytonjones@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
mailto:reisenberg@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
mailto:simon.peytonjones@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
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
mailto:reisenberg@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
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
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
mailto:arnaud.spiwack@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
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,
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
On 2024-03-14 14:32, Arnaud Spiwack wrote: proposing) thread phrase programs programs there's then 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@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@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

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
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@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
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
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
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
wrote: I've added a comment to the GitHub thread (
https://github.com/ghc-proposals/ghc-proposals/pull/631#issuecomment-1983060... )
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...
<
https://github.com/shlevy/ghc-proposals/blob/io-exitcode/proposals/0631-main...
.
PS: I tend to agree with Richard that requiring an ExitStatus
instance
is the preferable option. But food for thought for the proposal
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
mailto:simon.peytonjones@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
mailto:reisenberg@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
mailto:simon.peytonjones@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
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
mailto:reisenberg@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
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
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
mailto:arnaud.spiwack@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
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 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
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
return value.
The only change to the current behaviour is
`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
On 2024-03-14 14:32, Arnaud Spiwack wrote: proposing) thread phrase programs programs the the code. there's the that 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@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@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
-- -- Matthías Páll Gissurarson http://mpg.is/

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
disable the warning.
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.
On Fri, 15 Mar 2024 at 15:32, Matthías Páll Gissurarson
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
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@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
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
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
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
wrote: I've added a comment to the GitHub thread (
https://github.com/ghc-proposals/ghc-proposals/pull/631#issuecomment-1983060... )
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...
<
https://github.com/shlevy/ghc-proposals/blob/io-exitcode/proposals/0631-main...
. > > PS: I tend to agree with Richard that requiring an ExitStatus instance > is the preferable option. But food for thought for the proposal
> 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 >
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 >
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 >
mailto:simon.peytonjones@gmail.com> wrote: > > I am a little worried about breaking programs > in an innocent-looking `return 0`, just because some > other languages like to end programs with that
> > > 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 >
mailto:reisenberg@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 > 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
> that end in an innocent-looking `return 0`, just because > some other languages like to end programs with
> 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 >
mailto:arnaud.spiwack@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 > 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 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
> 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
> return value. > > The only change to the current behaviour is
> `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
On 2024-03-14 14:32, Arnaud Spiwack wrote: proposing) thread that end phrase programs programs that the the code. there's the that 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@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@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@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@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.

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
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
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@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
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
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
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
wrote: > I've added a comment to the GitHub thread > ( > https://github.com/ghc-proposals/ghc-proposals/pull/631#issuecomment-1983060... ) > > 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... > < > https://github.com/shlevy/ghc-proposals/blob/io-exitcode/proposals/0631-main...
> . > > > > PS: I tend to agree with Richard that requiring an ExitStatus instance > > is the preferable option. But food for thought for the proposal
> > 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 > >
> 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 > > > 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 > > > mailto:simon.peytonjones@gmail.com> wrote: > > > > I am a little worried about breaking programs > > in an innocent-looking `return 0`, just because some > > other languages like to end programs with that
> > > > > > 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 > >
> mailto:reisenberg@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 > > 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
> > that end in an innocent-looking `return 0`, just because > > some other languages like to end programs with
> > 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 > >
> mailto:arnaud.spiwack@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 > > 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 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
> > 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
> > return value. > > > > The only change to the current behaviour is
> > `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
On 2024-03-14 14:32, Arnaud Spiwack wrote: proposing) thread that end phrase programs programs that the the code. there's the that 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@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@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@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@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@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

@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
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
On 2024-03-19 15:15, Arnaud Spiwack wrote: 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
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
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@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
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
wrote: > > > I've added a comment to the GitHub thread > > ( > > https://github.com/ghc-proposals/ghc-proposals/pull/631#issuecomment-1983060...
) > > > > 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...
> > < > >
> > > . > > > > > > PS: I tend to agree with Richard that requiring an ExitStatus instance > > > is the preferable option. But food for thought for the
thread > > > when that conversation happens there: should that be gated behind an > > > extension? In which case it won't become the default before
next > > > language edition. > > > > > > /Arnaud > > > > > > On Mon, 4 Mar 2024 at 21:35, Simon Peyton Jones > > >
> > > 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 > > > 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 > > >
> > > 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 > > > 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 > > >
> > mailto:simon.peytonjones@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 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 > > >
> > mailto:reisenberg@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 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 > > >
> > mailto:arnaud.spiwack@tweag.io> wrote: > > > > > > Dear all, > > > > > > Shea Levy proposes to do something with 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
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
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
https://github.com/shlevy/ghc-proposals/blob/io-exitcode/proposals/0631-main... proposal the transition transition think program the that that 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@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@haskell.org >
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@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@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@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@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.

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
@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
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
On 2024-03-19 15:15, Arnaud Spiwack wrote: 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
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
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@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
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
wrote: > > > > > I've added a comment to the GitHub thread > > > ( > > > > https://github.com/ghc-proposals/ghc-proposals/pull/631#issuecomment-1983060... > ) > > > > > > 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... > > > < > > > > https://github.com/shlevy/ghc-proposals/blob/io-exitcode/proposals/0631-main... > > > > > . > > > > > > > > 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 > > > > >> > > > 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 > > > > >> > > > 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 > > > > > > > mailto:simon.peytonjones@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 > > > > > > > mailto:reisenberg@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 > > > > > > > mailto:arnaud.spiwack@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@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@haskell.org > > > https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee > > _______________________________________________ > ghc-steering-committee mailing list > ghc-steering-committee@haskell.org > https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee > _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@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@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@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@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@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

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

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
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@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.

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
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
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@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@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

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@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
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
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@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@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.

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
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@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
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
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@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@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.

I think we can discount 1a because it doesn't satisfy the stability
principles, right?
Out of the others, I would probably go with 1b or 3a as the most
predictable behaviours. I also like Simon's (4) (gated by an extension,
that we hope to enable in GHC2027).
Cheers
Simon
On Tue, 26 Mar 2024 at 09:35, Arnaud Spiwack
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
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@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@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

@SImonPJ I didn't include these two options because I hadn't understood
that they had any backing.
Personally: I don't like (1c) and (4)
- (1c) doesn't really address Shea's concern that the behaviour is
currently surprising, as you need to actively turn an extension on to have
the new behaviour, so you need to already know that the default behaviour
is counterintuitive.
- (4) is weird without type classes. Like what happens if I `type T =
ExitCode; main :: IO T`? Certainly `main` must not return with exit code 0.
We are having an issue here, the typical bikeshedding issue I imagine, that
there's about 1 proposal per member of the committee. I'm not sure how to
solve this efficiently, but I don't think it'll be easy to drive consensus.
I did ask Shea for his favoured options. He told me that if he can't have
1a, he prefers 3a (I promise I didn't influence him!).
On Thu, 28 Mar 2024 at 09:18, Simon Marlow
I think we can discount 1a because it doesn't satisfy the stability principles, right?
Out of the others, I would probably go with 1b or 3a as the most predictable behaviours. I also like Simon's (4) (gated by an extension, that we hope to enable in GHC2027).
Cheers Simon
On Tue, 26 Mar 2024 at 09:35, Arnaud Spiwack
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
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@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@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.

Ok, so, after an extended period of time (which, obviously, is my fault),
we essentially have one option per opinion (well, I guess 3a and 4 have
two, but that's not really what consensus is like). Simon, the other day,
advised me to reduce the number of choices based on Shea's preferences. I
decided to not include Shea's original proposal of doing the backward
incompatible change without extension as I believe that it is contrary to
the spirit of the language editions and all that.
*I'm calling for a vote* on the three following options. As per our
customs, this is preference voting please order the following options. If
you want to vote against an option, rank it after “That's it” (or omit it
altogether). Explanation of the summary below
I'm leaving the vote open until *Wednesday 1st May*. After which, I'll
tally, and synthesise the committee's final position.
2. [Summary: 00WWWN] No change in behaviour, just add a warning when `main`
has a type that isn't `main :: IO ()` or `main :: IO Void`, very much
including `main :: IO ExitCode` (Shae's second favourite alternative)
3a. [Summary: -XNoWombat: 00WWWW / -XWombat: TTETET] A warning is added as
in 2, but, additionally, an extension is introduced. When the extension is
turned on, we always call the proposed `ExitStatus` type class on the
returned value to determine the program's exit code. (Shae's favourite
alternative)
4. [Summary: -XNoWombat: 00000N / -XWombat 00I00N] No warning is
introduced, but an extension is. When the extension is turned on,
everything is as today, except when `main :: IO ExitCode`, in which case we
program's exit code is the exit code returned by `main` (Simon PJ's
favourite)
That's it
------
The summaries are based on the following examples. Each get a letter
representing the behaviour under the proposal, as described in the legend
The 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 ... }
The 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.
- I: The exit code is the returned value (only apply to `main :: IO
ExitCode`).
- N: not available under this alternative
On Thu, 28 Mar 2024 at 16:18, Arnaud Spiwack
@SImonPJ I didn't include these two options because I hadn't understood that they had any backing.
Personally: I don't like (1c) and (4) - (1c) doesn't really address Shea's concern that the behaviour is currently surprising, as you need to actively turn an extension on to have the new behaviour, so you need to already know that the default behaviour is counterintuitive. - (4) is weird without type classes. Like what happens if I `type T = ExitCode; main :: IO T`? Certainly `main` must not return with exit code 0.
We are having an issue here, the typical bikeshedding issue I imagine, that there's about 1 proposal per member of the committee. I'm not sure how to solve this efficiently, but I don't think it'll be easy to drive consensus.
I did ask Shea for his favoured options. He told me that if he can't have 1a, he prefers 3a (I promise I didn't influence him!).
On Thu, 28 Mar 2024 at 09:18, Simon Marlow
wrote: I think we can discount 1a because it doesn't satisfy the stability principles, right?
Out of the others, I would probably go with 1b or 3a as the most predictable behaviours. I also like Simon's (4) (gated by an extension, that we hope to enable in GHC2027).
Cheers Simon
On Tue, 26 Mar 2024 at 09:35, Arnaud Spiwack
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
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@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@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.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.

My ranking is
4
3a
2
That’s it.
/Matti Palli
On Mon, Apr 22, 2024 at 16:15 Arnaud Spiwack
Ok, so, after an extended period of time (which, obviously, is my fault), we essentially have one option per opinion (well, I guess 3a and 4 have two, but that's not really what consensus is like). Simon, the other day, advised me to reduce the number of choices based on Shea's preferences. I decided to not include Shea's original proposal of doing the backward incompatible change without extension as I believe that it is contrary to the spirit of the language editions and all that.
*I'm calling for a vote* on the three following options. As per our customs, this is preference voting please order the following options. If you want to vote against an option, rank it after “That's it” (or omit it altogether). Explanation of the summary below
I'm leaving the vote open until *Wednesday 1st May*. After which, I'll tally, and synthesise the committee's final position.
2. [Summary: 00WWWN] No change in behaviour, just add a warning when `main` has a type that isn't `main :: IO ()` or `main :: IO Void`, very much including `main :: IO ExitCode` (Shae's second favourite alternative) 3a. [Summary: -XNoWombat: 00WWWW / -XWombat: TTETET] A warning is added as in 2, but, additionally, an extension is introduced. When the extension is turned on, we always call the proposed `ExitStatus` type class on the returned value to determine the program's exit code. (Shae's favourite alternative) 4. [Summary: -XNoWombat: 00000N / -XWombat 00I00N] No warning is introduced, but an extension is. When the extension is turned on, everything is as today, except when `main :: IO ExitCode`, in which case we program's exit code is the exit code returned by `main` (Simon PJ's favourite) That's it
------
The summaries are based on the following examples. Each get a letter representing the behaviour under the proposal, as described in the legend
The 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 ... }
The 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. - I: The exit code is the returned value (only apply to `main :: IO ExitCode`). - N: not available under this alternative
On Thu, 28 Mar 2024 at 16:18, Arnaud Spiwack
wrote: @SImonPJ I didn't include these two options because I hadn't understood that they had any backing.
Personally: I don't like (1c) and (4) - (1c) doesn't really address Shea's concern that the behaviour is currently surprising, as you need to actively turn an extension on to have the new behaviour, so you need to already know that the default behaviour is counterintuitive. - (4) is weird without type classes. Like what happens if I `type T = ExitCode; main :: IO T`? Certainly `main` must not return with exit code 0.
We are having an issue here, the typical bikeshedding issue I imagine, that there's about 1 proposal per member of the committee. I'm not sure how to solve this efficiently, but I don't think it'll be easy to drive consensus.
I did ask Shea for his favoured options. He told me that if he can't have 1a, he prefers 3a (I promise I didn't influence him!).
On Thu, 28 Mar 2024 at 09:18, Simon Marlow
wrote: I think we can discount 1a because it doesn't satisfy the stability principles, right?
Out of the others, I would probably go with 1b or 3a as the most predictable behaviours. I also like Simon's (4) (gated by an extension, that we hope to enable in GHC2027).
Cheers Simon
On Tue, 26 Mar 2024 at 09:35, Arnaud Spiwack
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
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@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@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.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

I forgot to vote. Great job me!
Here's my vote:
3a
2
That's it.
On Mon, 22 Apr 2024 at 16:30, Matthías Páll Gissurarson
My ranking is
4 3a 2
That’s it.
/Matti Palli
On Mon, Apr 22, 2024 at 16:15 Arnaud Spiwack
wrote: Ok, so, after an extended period of time (which, obviously, is my fault), we essentially have one option per opinion (well, I guess 3a and 4 have two, but that's not really what consensus is like). Simon, the other day, advised me to reduce the number of choices based on Shea's preferences. I decided to not include Shea's original proposal of doing the backward incompatible change without extension as I believe that it is contrary to the spirit of the language editions and all that.
*I'm calling for a vote* on the three following options. As per our customs, this is preference voting please order the following options. If you want to vote against an option, rank it after “That's it” (or omit it altogether). Explanation of the summary below
I'm leaving the vote open until *Wednesday 1st May*. After which, I'll tally, and synthesise the committee's final position.
2. [Summary: 00WWWN] No change in behaviour, just add a warning when `main` has a type that isn't `main :: IO ()` or `main :: IO Void`, very much including `main :: IO ExitCode` (Shae's second favourite alternative) 3a. [Summary: -XNoWombat: 00WWWW / -XWombat: TTETET] A warning is added as in 2, but, additionally, an extension is introduced. When the extension is turned on, we always call the proposed `ExitStatus` type class on the returned value to determine the program's exit code. (Shae's favourite alternative) 4. [Summary: -XNoWombat: 00000N / -XWombat 00I00N] No warning is introduced, but an extension is. When the extension is turned on, everything is as today, except when `main :: IO ExitCode`, in which case we program's exit code is the exit code returned by `main` (Simon PJ's favourite) That's it
------
The summaries are based on the following examples. Each get a letter representing the behaviour under the proposal, as described in the legend
The 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 ... }
The 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. - I: The exit code is the returned value (only apply to `main :: IO ExitCode`). - N: not available under this alternative
On Thu, 28 Mar 2024 at 16:18, Arnaud Spiwack
wrote: @SImonPJ I didn't include these two options because I hadn't understood that they had any backing.
Personally: I don't like (1c) and (4) - (1c) doesn't really address Shea's concern that the behaviour is currently surprising, as you need to actively turn an extension on to have the new behaviour, so you need to already know that the default behaviour is counterintuitive. - (4) is weird without type classes. Like what happens if I `type T = ExitCode; main :: IO T`? Certainly `main` must not return with exit code 0.
We are having an issue here, the typical bikeshedding issue I imagine, that there's about 1 proposal per member of the committee. I'm not sure how to solve this efficiently, but I don't think it'll be easy to drive consensus.
I did ask Shea for his favoured options. He told me that if he can't have 1a, he prefers 3a (I promise I didn't influence him!).
On Thu, 28 Mar 2024 at 09:18, Simon Marlow
wrote: I think we can discount 1a because it doesn't satisfy the stability principles, right?
Out of the others, I would probably go with 1b or 3a as the most predictable behaviours. I also like Simon's (4) (gated by an extension, that we hope to enable in GHC2027).
Cheers Simon
On Tue, 26 Mar 2024 at 09:35, Arnaud Spiwack
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
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@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@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.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@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.

I don't feel strongly about this, but here's my vote 3a 4 that's it On Mon, Apr 22, 2024, at 09:15, Arnaud Spiwack wrote:
Ok, so, after an extended period of time (which, obviously, is my fault), we essentially have one option per opinion (well, I guess 3a and 4 have two, but that's not really what consensus is like). Simon, the other day, advised me to reduce the number of choices based on Shea's preferences. I decided to not include Shea's original proposal of doing the backward incompatible change without extension as I believe that it is contrary to the spirit of the language editions and all that.
*I'm calling for a vote* on the three following options. As per our customs, this is preference voting please order the following options. If you want to vote against an option, rank it after “That's it” (or omit it altogether). Explanation of the summary below
I'm leaving the vote open until *Wednesday 1st May*. After which, I'll tally, and synthesise the committee's final position.
2. [Summary: 00WWWN] No change in behaviour, just add a warning when `main` has a type that isn't `main :: IO ()` or `main :: IO Void`, very much including `main :: IO ExitCode` (Shae's second favourite alternative) 3a. [Summary: -XNoWombat: 00WWWW / -XWombat: TTETET] A warning is added as in 2, but, additionally, an extension is introduced. When the extension is turned on, we always call the proposed `ExitStatus` type class on the returned value to determine the program's exit code. (Shae's favourite alternative) 4. [Summary: -XNoWombat: 00000N / -XWombat 00I00N] No warning is introduced, but an extension is. When the extension is turned on, everything is as today, except when `main :: IO ExitCode`, in which case we program's exit code is the exit code returned by `main` (Simon PJ's favourite) That's it
------
The summaries are based on the following examples. Each get a letter representing the behaviour under the proposal, as described in the legend
The 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 ... }
The 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. - I: The exit code is the returned value (only apply to `main :: IO ExitCode`). - N: not available under this alternative
On Thu, 28 Mar 2024 at 16:18, Arnaud Spiwack
wrote: @SImonPJ I didn't include these two options because I hadn't understood that they had any backing.
Personally: I don't like (1c) and (4) - (1c) doesn't really address Shea's concern that the behaviour is currently surprising, as you need to actively turn an extension on to have the new behaviour, so you need to already know that the default behaviour is counterintuitive. - (4) is weird without type classes. Like what happens if I `type T = ExitCode; main :: IO T`? Certainly `main` must not return with exit code 0.
We are having an issue here, the typical bikeshedding issue I imagine, that there's about 1 proposal per member of the committee. I'm not sure how to solve this efficiently, but I don't think it'll be easy to drive consensus.
I did ask Shea for his favoured options. He told me that if he can't have 1a, he prefers 3a (I promise I didn't influence him!).
On Thu, 28 Mar 2024 at 09:18, Simon Marlow
wrote: I think we can discount 1a because it doesn't satisfy the stability principles, right?
Out of the others, I would probably go with 1b or 3a as the most predictable behaviours. I also like Simon's (4) (gated by an extension, that we hope to enable in GHC2027).
Cheers Simon
On Tue, 26 Mar 2024 at 09:35, Arnaud Spiwack
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
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@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@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.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

I vote: 2 3a That's it on the basis articulated in https://github.com/ghc-proposals/ghc-proposals/pull/631#issuecomment-1985236.... Adding a warning solves the problem of GHC surprising users by ignoring `main :: IO ExitCode`. Adding an extension for a tiny bit of convenience seems undermotivated IMHO, and I agree that making the change without extension is unjustified. I'm very sceptical of 4, because it introduces an extension that approximately nobody will think to use (and if it gets turned on by default at some point, we risk significant confusion with `main :: IO ExitCode` quietly doing different things on different language editions). Adam On 22/04/2024 15:15, Arnaud Spiwack wrote:
Ok, so, after an extended period of time (which, obviously, is my fault), we essentially have one option per opinion (well, I guess 3a and 4 have two, but that's not really what consensus is like). Simon, the other day, advised me to reduce the number of choices based on Shea's preferences. I decided to not include Shea's original proposal of doing the backward incompatible change without extension as I believe that it is contrary to the spirit of the language editions and all that.
*I'm calling for a vote* on the three following options. As per our customs, this is preference voting please order the following options. If you want to vote against an option, rank it after “That's it” (or omit it altogether). Explanation of the summary below
I'm leaving the vote open until *Wednesday 1st May*. After which, I'll tally, and synthesise the committee's final position.
2. [Summary: 00WWWN] No change in behaviour, just add a warning when `main` has a type that isn't `main :: IO ()` or `main :: IO Void`, very much including `main :: IO ExitCode` (Shae's second favourite alternative) 3a. [Summary: -XNoWombat: 00WWWW / -XWombat: TTETET] A warning is added as in 2, but, additionally, an extension is introduced. When the extension is turned on, we always call the proposed `ExitStatus` type class on the returned value to determine the program's exit code. (Shae's favourite alternative) 4. [Summary: -XNoWombat: 00000N / -XWombat 00I00N] No warning is introduced, but an extension is. When the extension is turned on, everything is as today, except when `main :: IO ExitCode`, in which case we program's exit code is the exit code returned by `main` (Simon PJ's favourite) That's it
------
The summaries are based on the following examples. Each get a letter representing the behaviour under the proposal, as described in the legend
The 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 ... }
The 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. - I: The exit code is the returned value (only apply to `main :: IO ExitCode`). - N: not available under this alternative
On Thu, 28 Mar 2024 at 16:18, Arnaud Spiwack
mailto:arnaud.spiwack@tweag.io> wrote: @SImonPJ I didn't include these two options because I hadn't understood that they had any backing.
Personally: I don't like (1c) and (4) - (1c) doesn't really address Shea's concern that the behaviour is currently surprising, as you need to actively turn an extension on to have the new behaviour, so you need to already know that the default behaviour is counterintuitive. - (4) is weird without type classes. Like what happens if I `type T = ExitCode; main :: IO T`? Certainly `main` must not return with exit code 0.
We are having an issue here, the typical bikeshedding issue I imagine, that there's about 1 proposal per member of the committee. I'm not sure how to solve this efficiently, but I don't think it'll be easy to drive consensus.
I did ask Shea for his favoured options. He told me that if he can't have 1a, he prefers 3a (I promise I didn't influence him!).
On Thu, 28 Mar 2024 at 09:18, Simon Marlow
mailto:marlowsd@gmail.com> wrote: I think we can discount 1a because it doesn't satisfy the stability principles, right?
Out of the others, I would probably go with 1b or 3a as the most predictable behaviours. I also like Simon's (4) (gated by an extension, that we hope to enable in GHC2027).
Cheers Simon
On Tue, 26 Mar 2024 at 09:35, Arnaud Spiwack
mailto:arnaud.spiwack@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
mailto:malte.ott@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 _______________________________________________
-- 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

I am not thrilled by having this three voting options. e.g. I think the behaviour in 4. is fine and maybe even better than the type class approach, but since this is coupled with not having a warning, its definitely worse. 3a 2 4 Also: If we implement 3a and then later people are against adding the extension to a language edition because it might error on a few programs I will be annoyed. Best Malte On 2024-04-22 16:15, Arnaud Spiwack wrote:
Ok, so, after an extended period of time (which, obviously, is my fault), we essentially have one option per opinion (well, I guess 3a and 4 have two, but that's not really what consensus is like). Simon, the other day, advised me to reduce the number of choices based on Shea's preferences. I decided to not include Shea's original proposal of doing the backward incompatible change without extension as I believe that it is contrary to the spirit of the language editions and all that.
*I'm calling for a vote* on the three following options. As per our customs, this is preference voting please order the following options. If you want to vote against an option, rank it after “That's it” (or omit it altogether). Explanation of the summary below
I'm leaving the vote open until *Wednesday 1st May*. After which, I'll tally, and synthesise the committee's final position.
2. [Summary: 00WWWN] No change in behaviour, just add a warning when `main` has a type that isn't `main :: IO ()` or `main :: IO Void`, very much including `main :: IO ExitCode` (Shae's second favourite alternative) 3a. [Summary: -XNoWombat: 00WWWW / -XWombat: TTETET] A warning is added as in 2, but, additionally, an extension is introduced. When the extension is turned on, we always call the proposed `ExitStatus` type class on the returned value to determine the program's exit code. (Shae's favourite alternative) 4. [Summary: -XNoWombat: 00000N / -XWombat 00I00N] No warning is introduced, but an extension is. When the extension is turned on, everything is as today, except when `main :: IO ExitCode`, in which case we program's exit code is the exit code returned by `main` (Simon PJ's favourite) That's it
------
The summaries are based on the following examples. Each get a letter representing the behaviour under the proposal, as described in the legend
The 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 ... }
The 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. - I: The exit code is the returned value (only apply to `main :: IO ExitCode`). - N: not available under this alternative
On Thu, 28 Mar 2024 at 16:18, Arnaud Spiwack
wrote: @SImonPJ I didn't include these two options because I hadn't understood that they had any backing.
Personally: I don't like (1c) and (4) - (1c) doesn't really address Shea's concern that the behaviour is currently surprising, as you need to actively turn an extension on to have the new behaviour, so you need to already know that the default behaviour is counterintuitive. - (4) is weird without type classes. Like what happens if I `type T = ExitCode; main :: IO T`? Certainly `main` must not return with exit code 0.
We are having an issue here, the typical bikeshedding issue I imagine, that there's about 1 proposal per member of the committee. I'm not sure how to solve this efficiently, but I don't think it'll be easy to drive consensus.
I did ask Shea for his favoured options. He told me that if he can't have 1a, he prefers 3a (I promise I didn't influence him!).
On Thu, 28 Mar 2024 at 09:18, Simon Marlow
wrote: I think we can discount 1a because it doesn't satisfy the stability principles, right?
Out of the others, I would probably go with 1b or 3a as the most predictable behaviours. I also like Simon's (4) (gated by an extension, that we hope to enable in GHC2027).
Cheers Simon
On Tue, 26 Mar 2024 at 09:35, Arnaud Spiwack
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
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@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@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.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.

Let me remind everybody of this thread: votes close on Wednesday.
Simon M, Simon PJ, Chris, Moritz, I'd love to have your opinion.
PS: Malte, I agree and I don't love the reduced choice either. But many
choices seemed to prevent opinions from coalescing. I don't think there's
an easy solution here. Generally, my opinion is that bikeshedding issues
aren't very-well suited to being resolved by committees. So we have to
compromise to move forward.
/Arnaud
On Mon, 22 Apr 2024 at 16:15, Arnaud Spiwack
Ok, so, after an extended period of time (which, obviously, is my fault), we essentially have one option per opinion (well, I guess 3a and 4 have two, but that's not really what consensus is like). Simon, the other day, advised me to reduce the number of choices based on Shea's preferences. I decided to not include Shea's original proposal of doing the backward incompatible change without extension as I believe that it is contrary to the spirit of the language editions and all that.
*I'm calling for a vote* on the three following options. As per our customs, this is preference voting please order the following options. If you want to vote against an option, rank it after “That's it” (or omit it altogether). Explanation of the summary below
I'm leaving the vote open until *Wednesday 1st May*. After which, I'll tally, and synthesise the committee's final position.
2. [Summary: 00WWWN] No change in behaviour, just add a warning when `main` has a type that isn't `main :: IO ()` or `main :: IO Void`, very much including `main :: IO ExitCode` (Shae's second favourite alternative) 3a. [Summary: -XNoWombat: 00WWWW / -XWombat: TTETET] A warning is added as in 2, but, additionally, an extension is introduced. When the extension is turned on, we always call the proposed `ExitStatus` type class on the returned value to determine the program's exit code. (Shae's favourite alternative) 4. [Summary: -XNoWombat: 00000N / -XWombat 00I00N] No warning is introduced, but an extension is. When the extension is turned on, everything is as today, except when `main :: IO ExitCode`, in which case we program's exit code is the exit code returned by `main` (Simon PJ's favourite) That's it
------
The summaries are based on the following examples. Each get a letter representing the behaviour under the proposal, as described in the legend
The 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 ... }
The 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. - I: The exit code is the returned value (only apply to `main :: IO ExitCode`). - N: not available under this alternative
On Thu, 28 Mar 2024 at 16:18, Arnaud Spiwack
wrote: @SImonPJ I didn't include these two options because I hadn't understood that they had any backing.
Personally: I don't like (1c) and (4) - (1c) doesn't really address Shea's concern that the behaviour is currently surprising, as you need to actively turn an extension on to have the new behaviour, so you need to already know that the default behaviour is counterintuitive. - (4) is weird without type classes. Like what happens if I `type T = ExitCode; main :: IO T`? Certainly `main` must not return with exit code 0.
We are having an issue here, the typical bikeshedding issue I imagine, that there's about 1 proposal per member of the committee. I'm not sure how to solve this efficiently, but I don't think it'll be easy to drive consensus.
I did ask Shea for his favoured options. He told me that if he can't have 1a, he prefers 3a (I promise I didn't influence him!).
On Thu, 28 Mar 2024 at 09:18, Simon Marlow
wrote: I think we can discount 1a because it doesn't satisfy the stability principles, right?
Out of the others, I would probably go with 1b or 3a as the most predictable behaviours. I also like Simon's (4) (gated by an extension, that we hope to enable in GHC2027).
Cheers Simon
On Tue, 26 Mar 2024 at 09:35, Arnaud Spiwack
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
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@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@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.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.

My preference is 4 3a 2
On 29 Apr 2024, at 08:26, Arnaud Spiwack
wrote: Let me remind everybody of this thread: votes close on Wednesday.
Simon M, Simon PJ, Chris, Moritz, I'd love to have your opinion.
PS: Malte, I agree and I don't love the reduced choice either. But many choices seemed to prevent opinions from coalescing. I don't think there's an easy solution here. Generally, my opinion is that bikeshedding issues aren't very-well suited to being resolved by committees. So we have to compromise to move forward.
/Arnaud
On Mon, 22 Apr 2024 at 16:15, Arnaud Spiwack
mailto:arnaud.spiwack@tweag.io> wrote: Ok, so, after an extended period of time (which, obviously, is my fault), we essentially have one option per opinion (well, I guess 3a and 4 have two, but that's not really what consensus is like). Simon, the other day, advised me to reduce the number of choices based on Shea's preferences. I decided to not include Shea's original proposal of doing the backward incompatible change without extension as I believe that it is contrary to the spirit of the language editions and all that.
I'm calling for a vote on the three following options. As per our customs, this is preference voting please order the following options. If you want to vote against an option, rank it after “That's it” (or omit it altogether). Explanation of the summary below
I'm leaving the vote open until Wednesday 1st May. After which, I'll tally, and synthesise the committee's final position.
2. [Summary: 00WWWN] No change in behaviour, just add a warning when `main` has a type that isn't `main :: IO ()` or `main :: IO Void`, very much including `main :: IO ExitCode` (Shae's second favourite alternative) 3a. [Summary: -XNoWombat: 00WWWW / -XWombat: TTETET] A warning is added as in 2, but, additionally, an extension is introduced. When the extension is turned on, we always call the proposed `ExitStatus` type class on the returned value to determine the program's exit code. (Shae's favourite alternative) 4. [Summary: -XNoWombat: 00000N / -XWombat 00I00N] No warning is introduced, but an extension is. When the extension is turned on, everything is as today, except when `main :: IO ExitCode`, in which case we program's exit code is the exit code returned by `main` (Simon PJ's favourite) That's it
------
The summaries are based on the following examples. Each get a letter representing the behaviour under the proposal, as described in the legend
The 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 ... }
The 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. - I: The exit code is the returned value (only apply to `main :: IO ExitCode`). - N: not available under this alternative
On Thu, 28 Mar 2024 at 16:18, Arnaud Spiwack
mailto:arnaud.spiwack@tweag.io> wrote: @SImonPJ I didn't include these two options because I hadn't understood that they had any backing.
Personally: I don't like (1c) and (4) - (1c) doesn't really address Shea's concern that the behaviour is currently surprising, as you need to actively turn an extension on to have the new behaviour, so you need to already know that the default behaviour is counterintuitive. - (4) is weird without type classes. Like what happens if I `type T = ExitCode; main :: IO T`? Certainly `main` must not return with exit code 0.
We are having an issue here, the typical bikeshedding issue I imagine, that there's about 1 proposal per member of the committee. I'm not sure how to solve this efficiently, but I don't think it'll be easy to drive consensus.
I did ask Shea for his favoured options. He told me that if he can't have 1a, he prefers 3a (I promise I didn't influence him!).
On Thu, 28 Mar 2024 at 09:18, Simon Marlow
mailto:marlowsd@gmail.com> wrote: I think we can discount 1a because it doesn't satisfy the stability principles, right?
Out of the others, I would probably go with 1b or 3a as the most predictable behaviours. I also like Simon's (4) (gated by an extension, that we hope to enable in GHC2027).
Cheers Simon
On Tue, 26 Mar 2024 at 09:35, Arnaud Spiwack
mailto:arnaud.spiwack@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
mailto:malte.ott@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@haskell.org mailto:ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
-- Arnaud Spiwack Director, Research at https://moduscreate.com https://moduscreate.com/ and https://tweag.io https://tweag.io/. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org mailto:ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
-- Arnaud Spiwack Director, Research at https://moduscreate.com https://moduscreate.com/ and https://tweag.io https://tweag.io/.
-- Arnaud Spiwack Director, Research at https://moduscreate.com https://moduscreate.com/ and https://tweag.io https://tweag.io/.
-- Arnaud Spiwack Director, Research at https://moduscreate.com https://moduscreate.com/ and https://tweag.io https://tweag.io/. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org mailto:ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

Arnaud
4. [Summary: -XNoWombat: 00000N / -XWombat 00I00N] No warning is
introduced, but an extension is. When the extension is turned on,
everything is as today, except when `main :: IO ExitCode`, in which case we
program's exit code is the exit code returned by `main` (Simon PJ's
favourite)
Actually I didn't say anything about warnings when suggesting (4). If we
adopted (4) *we'd surely want a warning like (2) when main returns a type
other than (), Void, or ExitCode*. So I'm going to vote on that basis
4 (with warning)
3a
2
that's it
Note that 4 (with warning) amounts to the same as (3a) with three built-in
instances for (), Void, and ExitCode. The difference is that 3a allows you
to have new types that all map to ExitCode. I don't think we have (nearly)
enough evidence to justify that extra complexity. If we get that evidence
we can smoothly move from (4-with-warning) to (3a); but not vice versa.
Because (4-with-warning) is effectively a special case of (3a).
Finally, with 3a there is a question of whether it is
- an error for main to return a type that is not an instance of
ExitStatus
- or a warning
The former is a breaking change; the latter is not. The proposal specifies
the latter, only it's not clear from the proposal whether you get a
warning. I think you should.
Simon
On Mon, 22 Apr 2024 at 15:15, Arnaud Spiwack
Ok, so, after an extended period of time (which, obviously, is my fault), we essentially have one option per opinion (well, I guess 3a and 4 have two, but that's not really what consensus is like). Simon, the other day, advised me to reduce the number of choices based on Shea's preferences. I decided to not include Shea's original proposal of doing the backward incompatible change without extension as I believe that it is contrary to the spirit of the language editions and all that.
*I'm calling for a vote* on the three following options. As per our customs, this is preference voting please order the following options. If you want to vote against an option, rank it after “That's it” (or omit it altogether). Explanation of the summary below
I'm leaving the vote open until *Wednesday 1st May*. After which, I'll tally, and synthesise the committee's final position.
2. [Summary: 00WWWN] No change in behaviour, just add a warning when `main` has a type that isn't `main :: IO ()` or `main :: IO Void`, very much including `main :: IO ExitCode` (Shae's second favourite alternative) 3a. [Summary: -XNoWombat: 00WWWW / -XWombat: TTETET] A warning is added as in 2, but, additionally, an extension is introduced. When the extension is turned on, we always call the proposed `ExitStatus` type class on the returned value to determine the program's exit code. (Shae's favourite alternative) 4. [Summary: -XNoWombat: 00000N / -XWombat 00I00N] No warning is introduced, but an extension is. When the extension is turned on, everything is as today, except when `main :: IO ExitCode`, in which case we program's exit code is the exit code returned by `main` (Simon PJ's favourite) That's it
------
The summaries are based on the following examples. Each get a letter representing the behaviour under the proposal, as described in the legend
The 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 ... }
The 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. - I: The exit code is the returned value (only apply to `main :: IO ExitCode`). - N: not available under this alternative
On Thu, 28 Mar 2024 at 16:18, Arnaud Spiwack
wrote: @SImonPJ I didn't include these two options because I hadn't understood that they had any backing.
Personally: I don't like (1c) and (4) - (1c) doesn't really address Shea's concern that the behaviour is currently surprising, as you need to actively turn an extension on to have the new behaviour, so you need to already know that the default behaviour is counterintuitive. - (4) is weird without type classes. Like what happens if I `type T = ExitCode; main :: IO T`? Certainly `main` must not return with exit code 0.
We are having an issue here, the typical bikeshedding issue I imagine, that there's about 1 proposal per member of the committee. I'm not sure how to solve this efficiently, but I don't think it'll be easy to drive consensus.
I did ask Shea for his favoured options. He told me that if he can't have 1a, he prefers 3a (I promise I didn't influence him!).
On Thu, 28 Mar 2024 at 09:18, Simon Marlow
wrote: I think we can discount 1a because it doesn't satisfy the stability principles, right?
Out of the others, I would probably go with 1b or 3a as the most predictable behaviours. I also like Simon's (4) (gated by an extension, that we hope to enable in GHC2027).
Cheers Simon
On Tue, 26 Mar 2024 at 09:35, Arnaud Spiwack
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
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@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@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.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

On Mon, 29 Apr 2024 at 17:58, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Actually I didn't say anything about warnings when suggesting (4). If we adopted (4) *we'd surely want a warning like (2) when main returns a type other than (), Void, or ExitCode*. So I'm going to vote on that basis
Argl! My misunderstanding, sorry. Would anyone change their vote if we change 4 to: -XNoWombat: 00WWWN / -XWombat 00IWWN]? I believe Malte will. Anyone else? (For 3a, I did specify that -XWombat gives errors on types which aren't instances of ExitStatus)

Dear friends,
I ask to abstain from this vote, as I’m experiencing some medical issues,
which require my full attention right now.
Thank you!
Best,
Moritz
On Tue, 30 Apr 2024 at 8:20 PM, Arnaud Spiwack
On Mon, 29 Apr 2024 at 17:58, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Actually I didn't say anything about warnings when suggesting (4). If we adopted (4) *we'd surely want a warning like (2) when main returns a type other than (), Void, or ExitCode*. So I'm going to vote on that basis
Argl! My misunderstanding, sorry.
Would anyone change their vote if we change 4 to: -XNoWombat: 00WWWN / -XWombat 00IWWN]? I believe Malte will. Anyone else?
(For 3a, I did specify that -XWombat gives errors on types which aren't instances of ExitStatus) _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

Moritz,
No worries. Take good care of yourself.
On Tue, 30 Apr 2024 at 14:37, Moritz Angermann
Dear friends,
I ask to abstain from this vote, as I’m experiencing some medical issues, which require my full attention right now.
Thank you!
Best, Moritz
On Tue, 30 Apr 2024 at 8:20 PM, Arnaud Spiwack
wrote: On Mon, 29 Apr 2024 at 17:58, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Actually I didn't say anything about warnings when suggesting (4). If we adopted (4) *we'd surely want a warning like (2) when main returns a type other than (), Void, or ExitCode*. So I'm going to vote on that basis
Argl! My misunderstanding, sorry.
Would anyone change their vote if we change 4 to: -XNoWombat: 00WWWN / -XWombat 00IWWN]? I believe Malte will. Anyone else?
(For 3a, I did specify that -XWombat gives errors on types which aren't instances of ExitStatus) _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@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.

With the change of definition for 4, I'm leaving the votes open until
tomorrow (Friday). I'll tally the vote Friday European afternoon (I want to
post a decision on Github before the end of the week, because I'm off all
week next week).
On Tue, 30 Apr 2024 at 14:38, Arnaud Spiwack
Moritz,
No worries. Take good care of yourself.
On Tue, 30 Apr 2024 at 14:37, Moritz Angermann
wrote: Dear friends,
I ask to abstain from this vote, as I’m experiencing some medical issues, which require my full attention right now.
Thank you!
Best, Moritz
On Tue, 30 Apr 2024 at 8:20 PM, Arnaud Spiwack
wrote: On Mon, 29 Apr 2024 at 17:58, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Actually I didn't say anything about warnings when suggesting (4). If we adopted (4) *we'd surely want a warning like (2) when main returns a type other than (), Void, or ExitCode*. So I'm going to vote on that basis
Argl! My misunderstanding, sorry.
Would anyone change their vote if we change 4 to: -XNoWombat: 00WWWN / -XWombat 00IWWN]? I believe Malte will. Anyone else?
(For 3a, I did specify that -XWombat gives errors on types which aren't instances of ExitStatus) _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@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.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.

As it turns out. 3a wins in the votes as currently laid out. But changing
Malte's vote to 4 first makes 4 the winner. Since it's my understanding
that if warnings are added Malte prefers 4. I'll ask Shea to modify his
proposal to 4.
On Thu, 2 May 2024 at 08:56, Arnaud Spiwack
With the change of definition for 4, I'm leaving the votes open until tomorrow (Friday). I'll tally the vote Friday European afternoon (I want to post a decision on Github before the end of the week, because I'm off all week next week).
On Tue, 30 Apr 2024 at 14:38, Arnaud Spiwack
wrote: Moritz,
No worries. Take good care of yourself.
On Tue, 30 Apr 2024 at 14:37, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Dear friends,
I ask to abstain from this vote, as I’m experiencing some medical issues, which require my full attention right now.
Thank you!
Best, Moritz
On Tue, 30 Apr 2024 at 8:20 PM, Arnaud Spiwack
wrote: On Mon, 29 Apr 2024 at 17:58, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Actually I didn't say anything about warnings when suggesting (4). If we adopted (4) *we'd surely want a warning like (2) when main returns a type other than (), Void, or ExitCode*. So I'm going to vote on that basis
Argl! My misunderstanding, sorry.
Would anyone change their vote if we change 4 to: -XNoWombat: 00WWWN / -XWombat 00IWWN]? I believe Malte will. Anyone else?
(For 3a, I did specify that -XWombat gives errors on types which aren't instances of ExitStatus) _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@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.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.

I agree with this plan of action, althougn I have no strong opinion about 3a vs. 4. On 2024-05-03 15:29, Arnaud Spiwack wrote:
As it turns out. 3a wins in the votes as currently laid out. But changing Malte's vote to 4 first makes 4 the winner. Since it's my understanding that if warnings are added Malte prefers 4. I'll ask Shea to modify his proposal to 4.
On Thu, 2 May 2024 at 08:56, Arnaud Spiwack
wrote: With the change of definition for 4, I'm leaving the votes open until tomorrow (Friday). I'll tally the vote Friday European afternoon (I want to post a decision on Github before the end of the week, because I'm off all week next week).
On Tue, 30 Apr 2024 at 14:38, Arnaud Spiwack
wrote: Moritz,
No worries. Take good care of yourself.
On Tue, 30 Apr 2024 at 14:37, Moritz Angermann < moritz.angermann@gmail.com> wrote:
Dear friends,
I ask to abstain from this vote, as I’m experiencing some medical issues, which require my full attention right now.
Thank you!
Best, Moritz
On Tue, 30 Apr 2024 at 8:20 PM, Arnaud Spiwack
wrote: On Mon, 29 Apr 2024 at 17:58, Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
Actually I didn't say anything about warnings when suggesting (4). If we adopted (4) *we'd surely want a warning like (2) when main returns a type other than (), Void, or ExitCode*. So I'm going to vote on that basis
Argl! My misunderstanding, sorry.
Would anyone change their vote if we change 4 to: -XNoWombat: 00WWWN / -XWombat 00IWWN]? I believe Malte will. Anyone else?
(For 3a, I did specify that -XWombat gives errors on types which aren't instances of ExitStatus) _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@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.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.
-- Arnaud Spiwack Director, Research at https://moduscreate.com and https://tweag.io.
_______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
participants (10)
-
Adam Gundry
-
Arnaud Spiwack
-
Chris Dornan
-
Eric Seidel
-
Malte Ott
-
Matthías Páll Gissurarson
-
Moritz Angermann
-
Richard Eisenberg
-
Simon Marlow
-
Simon Peyton Jones