<div dir="ltr"><div>I like the proposal. Particularly I like that "it's just namespacing", you can explain everything in terms of what entities are in scope with what names.<br></div><div><br></div><div>But one thing jars with me:</div><div><br></div><div>* In existing import statements, names are made available both qualified and unqualified unless you say "qualified", in which case only the qualified names are brought into scope.</div><div>* In this proposal, the "qualified" convention is extended to data/class/.. declarations, and to module exports. That's all fine.<br></div><div>* However, local modules use a different convention: you get only the qualified names by default unless you add the "import" keyword to bring into scope the unqualified names. This applies both to a local module declaration at the top level, and to the import of a local module in an import list.<br></div><div><br></div><div>Why the inconsistency here? Can't we use the "qualified" convention everywhere? I think I would rather prefer to write</div><div><br></div><div>   qualified module M (x,y) where ...</div><div><br></div><div>to make it clear that you have to refer to M.x qualified. That's a lot more consistent with import statements.<br></div><div><br></div><div>Perhaps the concern is that if you just "import M" and M contains local modules, we want those modules to be imported qualified by default. But we could just state that to be the case, so that you have to explicitly "import M (module N)" to bring N's entities into scope unqualified.<br></div><div><br></div><div>Cheers</div><div>Simon</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 14 Oct 2020 at 15:08, Spiwack, Arnaud <<a href="mailto:arnaud.spiwack@tweag.io">arnaud.spiwack@tweag.io</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><p style="margin:0px 0px 1.2em">Dear all,</p>
<p style="margin:0px 0px 1.2em">I would like to bring our own Richard Eisenberg’s proposal, #283: Local modules, to your attention.<br><a href="https://github.com/ghc-proposals/ghc-proposals/pull/283" target="_blank">https://github.com/ghc-proposals/ghc-proposals/pull/283</a></p>
<p style="margin:0px 0px 1.2em">The proposal is an attempt at solving the long debated issue that we can’t export qualified names out of a module (<em>e.g.</em> we may have to repeat <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">import qualified Data.Map as Map</code> and <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">import qualified Data.Set as Set</code> in every module in a project, rather than simply calling <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">import MyPrelude</code> which would take care of both and more), to improve scope management, and sharing names between types in the same files, while making namespaces more convenient to use in the process.</p>
<p style="margin:0px 0px 1.2em">It’s a pretty ambitious proposal, with quite a few interlocking pieces. Yet, in my opinion, they fit pretty well together. And I’m, as a potential consumer, very enthusiastic about it.</p>
<p style="margin:0px 0px 1.2em">Some highlight (though do read the whole thing):</p>
<ul style="margin:1.2em 0px;padding-left:2em">
<li style="margin:0.5em 0px">We can define modules inside of other modules, with the syntax <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">module Foo (some, optional, exports) where …</code></li>
<li style="margin:0.5em 0px">Like in the rest of Haskell, modules are no more than namespaces. Therefore you can open two <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">module Foo</code>, it will just merge the names in them</li>
<li style="margin:0.5em 0px">Values in local modules can be referred to, qualified, in the encompassing module</li>
<li style="margin:0.5em 0px">Local modules can be exported, importing them will import the name as qualified</li>
<li style="margin:0.5em 0px">A new <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">import module Foo</code> statement can be used in <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">let</code> and <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">where</code> clauses, it brings everything of the form <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">Foo.x</code> into scope unqualified for the scope of the <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">let</code> or <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">where</code></li>
</ul>
<p style="margin:0px 0px 1.2em">Additionally, there is a small point that is not integral to the rest of the proposal, where defining, say, a type</p>
<pre style="font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;white-space:pre-wrap;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);display:block;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248) none repeat scroll 0% 0%"><span><span style="color:rgb(51,51,51);font-weight:bold">data</span> <span style="color:rgb(68,85,136);font-weight:bold">T</span></span>
  = <span style="color:rgb(68,85,136);font-weight:bold">A</span>
  | <span style="color:rgb(68,85,136);font-weight:bold">B</span>
</code></pre>
<p style="margin:0px 0px 1.2em">Would create a local module named <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">T</code>, such that the constructors could be referred to as <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">T.A</code> and <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">T.B</code>. I mention it separately, because it causes the only (small) backward incompatibility (that is Haskell 2010 programs which stop compiling when you turn on <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">-XLocalModules</code>).</p>
<p style="margin:0px 0px 1.2em">I’m rather in favour of keeping it in, but it’s worth mentioning.</p>
<p style="margin:0px 0px 1.2em">I pretty much want all of these features in my daily programming, so, as I said above, I’m very enthusiastic for all of this. And I’m pretty happy with the realisation. Hence my recommending acceptance.</p>
<p style="margin:0px 0px 1.2em">/Arnaud</p>
<div title="MDH:PGRpdj5EZWFyIGFsbCw8L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2Pkkgd291bGQgbGlrZSB0byBi
cmluZyBvdXIgb3duIFJpY2hhcmQgRWlzZW5iZXJnJ3MgcHJvcG9zYWwgIzI4MzogTG9jYWwgbW9k
dWxlcyB0byB5b3VyIGF0dGVudGlvbi48L2Rpdj48ZGl2Pmh0dHBzOi8vZ2l0aHViLmNvbS9naGMt
cHJvcG9zYWxzL2doYy1wcm9wb3NhbHMvcHVsbC8yODM8L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2
PlRoZSBwcm9wb3NhbCBpcyBhbiBhdHRlbXB0IGF0IHNvbHZpbmcgdGhlIGxvbmcgZGViYXRlZCBp
c3N1ZSB0aGF0IHdlIGNhbid0IGV4cG9ydCBxdWFsaWZpZWQgbmFtZXMgb3V0IG9mIGEgbW9kdWxl
IChfZS5nLl8gd2UgbWF5IGhhdmUgdG8gcmVwZWF0IGBpbXBvcnQgcXVhbGlmaWVkIERhdGEuTWFw
IGFzIE1hcGAgYW5kIGBpbXBvcnQgcXVhbGlmaWVkIERhdGEuU2V0IGFzIFNldGAgaW4gZXZlcnkg
bW9kdWxlIGluIGEgcHJvamVjdCwgcmF0aGVyIHRoYW4gc2ltcGx5IGNhbGxpbmcgYGltcG9ydCBN
eVByZWx1ZGVgIHdoaWNoIHdvdWxkIHRha2UgY2FyZSBvZiBib3RoIGFuZCBtb3JlKSwgdG8gaW1w
cm92ZSBzY29wZSBtYW5hZ2VtZW50LCBhbmQgc2hhcmluZyBuYW1lcyBiZXR3ZWVuIHR5cGVzIGlu
IHRoZSBzYW1lIGZpbGVzLCB3aGlsZSBtYWtpbmcgbmFtZXNwYWNlcyBtb3JlIGNvbnZlbmllbnQg
dG8gdXNlIGluIHRoZSBwcm9jZXNzLjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+SXQncyBhIHBy
ZXR0eSBhbWJpdGlvdXMgcHJvcG9zYWwsIHdpdGggcXVpdGUgYSBmZXcgaW50ZXJsb2NraW5nIHBp
ZWNlcy4gWWV0LCBpbiBteSBvcGluaW9uLCB0aGV5IGZpdCBwcmV0dHkgd2VsbCB0b2dldGhlci4g
QW5kIEknbSwgYXMgYSBwb3RlbnRpYWwgY29uc3VtZXIsIHZlcnkgZW50aHVzaWFzdGljIGFib3V0
IGl0LjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+U29tZSBoaWdobGlnaHQgKHRob3VnaCBkbyBy
ZWFkIHRoZSB3aG9sZSB0aGluZyk6PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj4tIFdlIGNhbiBk
ZWZpbmUgbW9kdWxlcyBpbnNpZGUgb2Ygb3RoZXIgbW9kdWxlcywgd2l0aCB0aGUgc3ludGF4IGBt
b2R1bGUgRm9vIChzb21lLCBvcHRpb25hbCwgZXhwb3J0cykgd2hlcmUg4oCmYDwvZGl2PjxkaXY+
LSBMaWtlIGluIHRoZSByZXN0IG9mIEhhc2tlbGwsIG1vZHVsZXMgYXJlIG5vIG1vcmUgdGhhbiBu
YW1lc3BhY2VzLiBUaGVyZWZvcmUgeW91IGNhbiBvcGVuIHR3byBgbW9kdWxlIEZvb2AsIGl0IHdp
bGwganVzdCBtZXJnZSB0aGUgbmFtZXMgaW4gdGhlbTwvZGl2PjxkaXY+LSBWYWx1ZXMgaW4gbG9j
YWwgbW9kdWxlcyBjYW4gYmUgcmVmZXJyZWQgdG8sIHF1YWxpZmllZCwgaW4gdGhlIGVuY29tcGFz
c2luZyBtb2R1bGU8L2Rpdj48ZGl2Pi0gTG9jYWwgbW9kdWxlcyBjYW4gYmUgZXhwb3J0ZWQsIGlt
cG9ydGluZyB0aGVtIHdpbGwgaW1wb3J0IHRoZSBuYW1lIGFzIHF1YWxpZmllZDwvZGl2PjxkaXY+
LSBBIG5ldyBgaW1wb3J0IG1vZHVsZSBGb29gIHN0YXRlbWVudCBjYW4gYmUgdXNlZCBpbiBgbGV0
YCBhbmQgYHdoZXJlYCBjbGF1c2VzLCBpdCBicmluZ3MgZXZlcnl0aGluZyBvZiB0aGUgZm9ybSBg
Rm9vLnhgIGludG8gc2NvcGUgdW5xdWFsaWZpZWQgZm9yIHRoZSBzY29wZSBvZiB0aGUgYGxldGAg
b3IgYHdoZXJlYDwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+QWRkaXRpb25hbGx5LCB0aGVyZSBp
cyBhIHNtYWxsIHBvaW50IHRoYXQgaXMgbm90IGludGVncmFsIHRvIHRoZSByZXN0IG9mIHRoZSBw
cm9wb3NhbCwgd2hlcmUgZGVmaW5pbmcsIHNheSwgYSB0eXBlPC9kaXY+PGRpdj48YnI+PC9kaXY+
PGRpdj5gYGBoYXNrZWxsPC9kaXY+PGRpdj5kYXRhIFQ8L2Rpdj48ZGl2PiZuYnNwOyA9IEE8L2Rp
dj48ZGl2PiZuYnNwOyB8IEI8L2Rpdj48ZGl2PmBgYDwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+
V291bGQgY3JlYXRlIGEgbG9jYWwgbW9kdWxlIG5hbWVkIGBUYCwgc3VjaCB0aGF0IHRoZSBjb25z
dHJ1Y3RvcnMgY291bGQgYmUgcmVmZXJyZWQgdG8gYXMgYFQuQWAgYW5kIGBULkJgLiBJIG1lbnRp
b24gaXQgc2VwYXJhdGVseSwgYmVjYXVzZSBpdCBjYXVzZXMgdGhlIG9ubHkgKHNtYWxsKSBiYWNr
d2FyZCBpbmNvbXBhdGliaWxpdHkgKHRoYXQgaXMgSGFza2VsbCAyMDEwIHByb2dyYW1zIHdoaWNo
IHN0b3AgY29tcGlsaW5nIHdoZW4geW91IHR1cm4gb24gYC1YTG9jYWxNb2R1bGVzYCkuPC9kaXY+
PGRpdj48YnI+PC9kaXY+PGRpdj5JJ20gcmF0aGVyIGluIGZhdm91ciBvZiBrZWVwaW5nIGl0IGlu
LCBidXQgaXQncyB3b3J0aCBtZW50aW9uaW5nLjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+SSBw
cmV0dHkgbXVjaCB3YW50IGFsbCBvZiB0aGVzZSBmZWF0dXJlcyBpbiBteSBkYWlseSBwcm9ncmFt
bWluZywgc28sIGFzIEkgc2FpZCBhYm92ZSwgSSdtIHZlcnkgZW50aHVzaWFzdGljIGZvciBhbGwg
b2YgdGhpcy4gQW5kIEknbSBwcmV0dHkgaGFwcHkgd2l0aCB0aGUgcmVhbGlzYXRpb24uIEhlbmNl
IG15IHJlY29tbWVuZGluZyBhY2NlcHRhbmNlLjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+L0Fy
bmF1ZDxicj48L2Rpdj4=" style="height:0px;width:0px;max-height:0px;max-width:0px;overflow:hidden;font-size:0em;padding:0px;margin:0px"></div></div></div>
_______________________________________________<br>
ghc-steering-committee mailing list<br>
<a href="mailto:ghc-steering-committee@haskell.org" target="_blank">ghc-steering-committee@haskell.org</a><br>
<a href="https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee" rel="noreferrer" target="_blank">https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee</a><br>
</blockquote></div>