[ghc-steering-committee] #216: Qualified Do again, recommendation: accept the alternative

Alejandro Serrano Mena trupill at gmail.com
Sun Apr 12 19:31:28 UTC 2020


Hi,
I also lean towards the module-based approach.

Regards,
Alejandro

El dom., 12 abr. 2020 a las 8:02, Vitaly Bragilevsky (<bravit111 at gmail.com>)
escribió:

> HI,
>
> I prefer the module-based approach too. I agree that names such as (>>=)
> should not be explicitly imported if they are not used in the code
> explicitly.
>
> I also support the following Richard's idea:
>
> > - I think this extension would be considerably more ergonomic if the new
> operators were not named (>>=), etc., but instead something like
> qualifiedBind, qualifiedThen, etc. This means that defining modules needn't
> be delicate around importing the Prelude, and importing modules don't need
> to worry about record selectors causing name clashes, etc., if they are not
> using this new extension.
>
> This makes it easier to define such modules and use them if the new
> extension is not enabled.
>
> Vitaly
>
>
> пт, 10 апр. 2020 г. в 18:28, Iavor Diatchki <iavor.diatchki at gmail.com>:
>
>> Hello,
>>
>> My thoughts on this are on the git-hub thread, as I've been involved in
>> the discussion for quite a while.
>>
>> I am in alignment with Joachim, that we should accept the module-based
>> variant of the proposal.
>>
>> I don't have strong feelings on if the implicit names used by the
>> transformation should be in scope or just accessible via an import.
>> However, I think he makes a convincing argument that it would be pretty
>> weird to require names to be in scope that are not visible anywhere in the
>> source code, so following the choice we already made for ordinary `do` does
>> make sense to me.
>>
>> -Iavor
>> PS:  Arnaud, not that it matters very much, but RankNTypes are not part
>> of Haskell 2010.
>>
>>
>>
>>
>>
>> On Fri, Apr 10, 2020 at 6:51 AM Richard Eisenberg <rae at richarde.dev>
>> wrote:
>>
>>> Despite being the one to articulate "fully settled" and how to make
>>> builders with it, I now favor the module-based approach. Thanks, Joachim,
>>> for writing out pros and cons. I agree with the pros and con you listed
>>> with the module-based approach. Let's also look at some pros of the
>>> record-based approach:
>>>
>>> ➕ A single entity one can import, reexport, even rebind
>>> ➕ A single entity that can carry the documentation
>>> ➕ One module can export multiple builders
>>>
>>>
>>> With either of two module-system-improvement proposals (
>>> https://github.com/ghc-proposals/ghc-proposals/pull/283 or
>>> https://github.com/ghc-proposals/ghc-proposals/pull/295), these pros
>>> carry over to the module-based approach.
>>>
>>> The reason I switched camps, from favoring record-based to favoring
>>> module-based, is this argument, by John Ericson:
>>> https://github.com/ghc-proposals/ghc-proposals/pull/216#issuecomment-606109628
>>> Here, John is reacting to my complaint that the module-based solution will,
>>> to be ergonomic, require either #283 or #295. But John points out that we
>>> don't need to wait for #283 or #295: we can implement the module-based
>>> system right away. It will be usable (but sometimes clunky) right away. It
>>> will satisfy the problems in the motivation right away. All #283/#295 would
>>> do is make it less clunky.
>>>
>>> Put another way: let's imagine a Haskell with either of #283 or #295
>>> implemented. Then, I think, the module-based approach would be a very clear
>>> win, over a record-based approach with its one-off "fully settled" and
>>> strange restrictions on types. (The builder must have *some* record type,
>>> but any record type would do. There's nothing else like that anywhere.) So
>>> by choosing the record-based approach, we're cutting off access to the
>>> right design in the limit. Of course, #283/#295 are large proposals, still
>>> technically under discussion (but very quiet), and either one has a sizable
>>> implementation burden. I would never want to accept this current proposal
>>> in a way that would depend on #283/#295. But, as argued above, the
>>> module-based approach does not depend on these large proposals.
>>>
>>> My thoughts on the finer points:
>>>
>>> - I think the selectors should be in scope. It's simpler and less
>>> ambiguous this way, given the fact that one module can alias several
>>> modules to, say, M. I don't feel strongly on this point, though, and I see
>>> the arguments in the other direction.
>>> - I think this extension would be considerably more ergonomic if the new
>>> operators were not named (>>=), etc., but instead something like
>>> qualifiedBind, qualifiedThen, etc. This means that defining modules needn't
>>> be delicate around importing the Prelude, and importing modules don't need
>>> to worry about record selectors causing name clashes, etc., if they are not
>>> using this new extension.
>>>
>>> As we decide on this proposal, I would also like us to think about how
>>> this scales to other applications of rebindable syntax. For example, maybe
>>> we want M.if or M.[ x, y, z ] someday. I think the design *does* scale in
>>> such a way, which perhaps paves the way to deprecating -XRebindableSyntax.
>>>
>>> Richard
>>>
>>> On Apr 9, 2020, at 6:16 PM, Joachim Breitner <mail at joachim-breitner.de>
>>> wrote:
>>>
>>> Dear Committe,
>>>
>>> Proposal:
>>>
>>> https://github.com/tweag/ghc-proposals/blob/local-do/proposals/0000-local-do.rst
>>> Discussion (long, sorry):
>>> https://github.com/ghc-proposals/ghc-proposals/pull/216
>>>
>>>
>>> Summary:
>>>
>>> Over a year ago (on my birthday then) Arnaud created  a “local do”
>>> proposal that would be a more targetted variant of RebindableSyntax,
>>> just for “do”. In June, we sent it back because a simple syntactic
>>> desugaring to records didn’t quite seem right (bad type inference).
>>>
>>> In March, the authors can back with an alternative, which was using a
>>> Module name instead of a value of record type to indicate that monadic
>>> operations to use. This nicely solved the type system issues and meant
>>> that the translation can happen (in principle) in the parser or renamer
>>> stage. But some of us noticed that a builder record is nicer after all,
>>> and we can fix the type system issues, mostly by introducing a new
>>> concept
>>> of “fully settled type”; with analogies to TH stage restrictions.
>>>
>>> The authors updated the proposal accordingly, but also list the
>>> alternatives
>>> in the documents.
>>>
>>> Based on the GitHub thread we have varying opinions among the committee.
>>> Nevertheless, I think the authors have done a great and patient job so
>>> far, so
>>> we owe them a hopefully conclusive discussion.
>>>
>>> The main question we have to decide is:
>>>
>>>    record-based   or    module based
>>>
>>>
>>> Record based:
>>> ➕ A single entity one can import, reexport, even rebind
>>> ➕ A single entity that can carry the documentation
>>> ➕ One module can export multiple builders
>>> ➕ Looking forward, the builder could be dynamically constructed
>>>   (i.e. a local value)
>>> ➕ Concept of fully settled may be useful elsewhere in the future
>>>   and can be expanded
>>> ➖ Needs a new concept of “fully settled” that we don’t have elsewhere
>>> ➖ Initially, “fully settled” introduces staging restrictions;
>>>   builder values may not be usable everywhere where they are in scope.
>>> ➖ Lots of fluff on the defining side
>>>   (define a likely one-off record + a value)
>>> ➖ May require extensions (e.g. RankNTypes, ImpredicativeTypes)
>>>   on the defining side, even for a builder for the “normal” Monad
>>>   (see
>>> https://github.com/ghc-proposals/ghc-proposals/pull/216#issuecomment-600746723
>>>   for an example for the previous two points)
>>> ➕ Some compositionality (functions modifying builders), but
>>> ➖ not as universal as one would hope, as there is not a single builder
>>> type
>>>   (different qualified monads likely use different record type)
>>> ➕ Can support “passing arguments to do” via `(monadBuilder @Maybe).do`
>>>   or `(b cfg).do`
>>>   (once the notion of “fully settled” is powerful enough)
>>>
>>> Module based:
>>> ➕ Simpler to specify and understand:
>>>   Only affects parsing, possibly renaming. No interactions with the type
>>> system.
>>> ➕ Works out of the box with, say, `Prelude.` as the qualifier
>>> ➕ Benefits from future improvements to the module system
>>> ➖ Would need separate syntax for “passing arguments to do”, should we
>>> want that
>>> ➕ But if we had that, it can implement the record-based approach, by
>>> passing a
>>>   recoord to a suitable qualified do monad, as Iavor observes:
>>>
>>> https://github.com/ghc-proposals/ghc-proposals/pull/216#issuecomment-598859245
>>>
>>> The module-based approach would additionally raises the question whether
>>> * the desugaring to M.(>>) means (>>) as provided by (some) M”,
>>>   akin to how plain do notation works.
>>> * the desugaring to M.(>>) means just that (and requires (>>) to be
>>> imported as well),
>>>   akin to how RebindableSyntax works
>>>
>>>
>>> There was also a brief discussion of whether this should extend the set
>>> of operations involved to a `last` function that is used in the
>>> translation rule for a single-statement do notation, but it did not
>>> catch on.
>>>
>>>
>>> Recommendation:
>>>
>>> While both approaches are reasonable and have their merits, I recommend
>>> to accept the Module based approach. It supports most use-cases
>>> presented so far, in particular the Linear.do as envisioned by the
>>> authors, so it seems good enough™.
>>> Furthermore, it certainly is significantly simpler, given that it can
>>> be specified purely in terms of naming things, so we have a higher
>>> chance that this will work well with other existing and future language
>>> features.
>>>
>>> Should the committee follow that decision, I recommend to pick the
>>> variant where the value does not need to be in scope, so that its
>>> mechanism is close to the normal do notation, and that you can write
>>>
>>> import Linear (runLinear, other, stuff)
>>>>>>   Linear.do { … }
>>>
>>> without mucking with qualified imports or shadowing (>>). It seems odd
>>> to require the user to add ((>>), (>>=), fail) to an import list when
>>> you don’t actually mention that name anywhere.
>>>
>>>
>>>
>>>
>>> Cheers,
>>> Joachim
>>>
>>>
>>> --
>>> Joachim Breitner
>>>  mail at joachim-breitner.de
>>>  http://www.joachim-breitner.de/
>>>
>>>
>>> _______________________________________________
>>> ghc-steering-committee mailing list
>>> ghc-steering-committee at haskell.org
>>> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
>>>
>>>
>>> _______________________________________________
>>> ghc-steering-committee mailing list
>>> ghc-steering-committee at haskell.org
>>> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
>>>
>> _______________________________________________
>> ghc-steering-committee mailing list
>> ghc-steering-committee at haskell.org
>> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
>>
> _______________________________________________
> ghc-steering-committee mailing list
> ghc-steering-committee at haskell.org
> https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-steering-committee/attachments/20200412/0d3b5925/attachment-0001.html>


More information about the ghc-steering-committee mailing list