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

Spiwack, Arnaud arnaud.spiwack at tweag.io
Fri Apr 10 07:58:41 UTC 2020


As one of the authors, I'm going to engage only lightly in this
conversation.

Just a few comments, for the moment

  ➖ 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)
>

I don't believe this to hold. Impredicative record fields are plain Haskell
2010.

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

I am, to be honest, very uncomfortable with the idea: if I explicitly
didn't import something, I don't want it to be used in my program. A
counter-argument is that types appear in desugared programs which were not
imported, so maybe I'm overreacting. But I'm still uncomfortable. And it
doesn't look like it's less of a complication than the fully-settled
business.

Overall, I personally quite prefer the record-based alternative.

On Thu, Apr 9, 2020 at 7:17 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-steering-committee/attachments/20200410/3a7b87c8/attachment.html>


More information about the ghc-steering-committee mailing list