
Sorry to have been quiet after Joachim's soliciting more input from me,
Let me try to summarize why I prefer the records approach (and I think it
sort of boils down to the same intuition as Simon (Peyton Jones)'s reasons):
It boils down to: a record would define, in no ambiguous terms, a do
notation desugaring strategy. Whereas in the module-based approach, a given
do block is allowed to pick and mix different combinators from wherever it
wants; even if they don't go together very well.
- This makes it certain which combinators are working together. With the
modules, who's to say that I am not mistakenly taking `(>>)` from a
different location because I'm mixing modules together (and the module I
think I'm using doesn't actually export `(>>)`)? I'd eventually find out,
but it would be rather unpleasant to debug considering that I'm not even
seeing `M.>>` in my code.
- Error messages can tell me: “your builder doesn't support `>>`”, rather
than telling me, “You're not importing an `M.>>`” which is a less ambiguous
error.
This feature, overall, makes more sense to me with records.
On Mon, May 4, 2020 at 6:46 PM Tom Harding
I’m nervous to endorse any solution that requires implicit parameters generally, just because of the cognitive overhead involved in reading and understanding any code involving them. I think, for the particular problem of dynamic builders, the record approach ends up being more “idiomatic Haskell” (for my personal definition of idiomatic, of course).
That said, I can’t deny that the solution works! Moreover, given that I don’t have a concrete example of a problem in mind, I wouldn’t want to hold up a final decision.
Cheers, Tom
On 4 May 2020, at 16:22, Iavor Diatchki
wrote: You can define dynamic builders with the module based approach, there's an example on the GitHub thread.
Iavor
On Mon, May 4, 2020, 05:00 Tom Harding
wrote: I’ve been quiet so far because I think both outcomes are perfectly sensible, and I don’t think I have anything to add that hasn’t already been covered.
If really pushed, I’d perhaps have a slight bias towards the record-based approach, but really only because of the future possibility of dynamically constructing builders. However, I don’t think that preference is strong enough to be worth counting - I’m happy to abstain.
Thanks, Tom
On 2 May 2020, at 10:54, Cale Gibbard
wrote: I greatly prefer the earlier module-based version of this where the definitions of the relevant functions are simply obtained from the qualified module and we don't have to talk about fully-settled types to explain how expressions are going to desugar. Even if it's not quite true in the case of GHC's internals that desugaring comes entirely before typechecking, I think it's really very helpful in both understanding the language ourselves and in explaining it to beginners if we can at least think about it that way. The more that the translation from surface syntax to core factors into a bunch of individually comprehensible translations, the better.
On Sat, 2 May 2020 at 05:39, Joachim Breitner
wrote: Dear Committee,
it seems discussion has ebbed down. Are there any new arguments that can be brought forward? Did anyone have a change of mind which would bring us closer to (or farther away from) consensus? Or should we vote?
Simon Marlow, Chris, Cale, Tom: You have not stated an opinion. Do you have one?
Cheers, Joachim
Am Mittwoch, den 22.04.2020, 12:26 +0200 schrieb Joachim Breitner:
Dear Committe,
trying to summarize the discussion here.
The main decision seems to be: Record based or module based.
Record based is preferred by: Arnaud (one of the authors), SPJ
Module based is preferred by: Richard (after changing his mind), Eric, Iavor, Vitaly, Alejandro, me
This is not a vote, merely a summary of sentimenss. But it seems that maybe the onus to make stronger arguments for the record-based
is on Simon and Arnaud?
Related to the module based variant, there was some discussion about whether the * desugaring should go to a “qualified name”, that is then resolved like any manually written name (i.e. could conceptually be done in the parser) * or if it should go directly a suitable “original name” of a suitable function, even if not explicitly imported (i.e. could conceptually be done in the renamer, but not the parser)
I initially advocated for the latter, arguing with a “you shall not have to import stuff you do not write explicitly” rule. But Simon’s recent argument that
import qualified Monad as M
(i.e. _with_ qualification, but _without_ an import list) will give
approach the
developer a good user experience, and if they try to do things like
import Monad as M (runMonad) … M.do …
then, well, they shouldn’t. So I am happy to advocate for the module based approach with the “must be in scope” rule. But maybe we should keep the focus more on the fundamental question above.
We could keep in mind that eventually, people will ask for M.if; M.[ and other “qualified syntax”. But it seems that that will work equally well with either choice here.
Cheers, Joachim
-- Joachim Breitner mail@joachim-breitner.de http://www.joachim-breitner.de/
_______________________________________________ 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