[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