
Dear all, I would like to bring our own Richard Eisenberg’s proposal, #283: Local modules, to your attention. https://github.com/ghc-proposals/ghc-proposals/pull/283 The proposal is an attempt at solving the long debated issue that we can’t export qualified names out of a module (*e.g.* we may have to repeat import qualified Data.Map as Map and import qualified Data.Set as Set in every module in a project, rather than simply calling import MyPrelude 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. 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. Some highlight (though do read the whole thing): - We can define modules inside of other modules, with the syntax module Foo (some, optional, exports) where … - Like in the rest of Haskell, modules are no more than namespaces. Therefore you can open two module Foo, it will just merge the names in them - Values in local modules can be referred to, qualified, in the encompassing module - Local modules can be exported, importing them will import the name as qualified - A new import module Foo statement can be used in let and where clauses, it brings everything of the form Foo.x into scope unqualified for the scope of the let or where Additionally, there is a small point that is not integral to the rest of the proposal, where defining, say, a type data T = A | B Would create a local module named T, such that the constructors could be referred to as T.A and T.B. I mention it separately, because it causes the only (small) backward incompatibility (that is Haskell 2010 programs which stop compiling when you turn on -XLocalModules). I’m rather in favour of keeping it in, but it’s worth mentioning. 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. /Arnaud

Hi, very well written proposal, the motivation section is exemplary. In particular excited about the ability to locally open a module (something that I began to like when writing Ocaml).
Would it be equivalent to say that all traditional import declarations create local modules?
When reading the proposal, that was somehow automatically my mental model. So I hope it is true, and that we can explain things this way. This would actually rule out the alternative
Drop point (8) allowing extension of existing local modules. because `import qualified Foo as A; import qualified Bar as A` only works if local modules can be extended.
Should -XLocalModules be required to import a local module?
My gut feeling is yes. The knowledge that `Foo.Bar.baz` comes from an imported `Foo.Bar` should still be applicable, unless a language extension clearly tells you that something is different. So I am supportive. I could understand if someone argued “too big of a change for too little impact; makes Haskell more complicated” … but I won’t be that someone. Cheers, Joachim -- Joachim Breitner mail@joachim-breitner.de http://www.joachim-breitner.de/

In particular excited about the ability to locally open a module (something that I began to like when writing Ocaml).
It is also one of my favourite features in Ocaml. It's a fairly recent addition to Ocaml (10ish years ago, I would say?), and I believe it's fair to say that it had a profound impact on coding style throughout the community. For the better in my opinion.

I like the proposal as it stands.
El jue., 15 oct. 2020 a las 20:09, Spiwack, Arnaud (
In
particular excited about the ability to locally open a module (something that I began to like when writing Ocaml).
It is also one of my favourite features in Ocaml. It's a fairly recent addition to Ocaml (10ish years ago, I would say?), and I believe it's fair to say that it had a profound impact on coding style throughout the community. For the better in my opinion. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

Simon (Marlow):
Do I understand correctly that what you are objecting to is the following
syntax in the proposal
module M where
import module M where
And would rather have
qualified module M where
module M where
To mimic the import declaration behaviour?
On Sat, Oct 17, 2020 at 9:33 PM Alejandro Serrano Mena
I like the proposal as it stands.
El jue., 15 oct. 2020 a las 20:09, Spiwack, Arnaud (< arnaud.spiwack@tweag.io>) escribió:
In
particular excited about the ability to locally open a module (something that I began to like when writing Ocaml).
It is also one of my favourite features in Ocaml. It's a fairly recent addition to Ocaml (10ish years ago, I would say?), and I believe it's fair to say that it had a profound impact on coding style throughout the community. For the better in my opinion. _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

On Wed, 21 Oct 2020 at 07:40, Spiwack, Arnaud
Simon (Marlow):
Do I understand correctly that what you are objecting to is the following syntax in the proposal
module M where import module M where
And would rather have
qualified module M where module M where
To mimic the import declaration behaviour?
Yes. And instead of import M (module N) import M (import module N) we would write import M (qualified module N) import M (module N) It seems to me to be desirable to use the same convention for all of: * importing modules at the top level ([import M [qualified]) * importing a local module (import M ([qualified] module N)) * declaring a local module ([qualified] module M where ..) * exporting a local module (module M ([qualified] module M) where) and perhaps it would be a source of confusion if these were different, as in the proposal. (but it's hard to tell, since we don't have any experience with using the extension yet.) Richard, what do you think? Cheers Simon
On Sat, Oct 17, 2020 at 9:33 PM Alejandro Serrano Mena
wrote: I like the proposal as it stands.
El jue., 15 oct. 2020 a las 20:09, Spiwack, Arnaud (< arnaud.spiwack@tweag.io>) escribió:
In
particular excited about the ability to locally open a module (something that I began to like when writing Ocaml).
It is also one of my favourite features in Ocaml. It's a fairly recent addition to Ocaml (10ish years ago, I would say?), and I believe it's fair to say that it had a profound impact on coding style throughout the community. For the better in my opinion. _______________________________________________ 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

On Nov 1, 2020, at 5:41 AM, Simon Marlow
wrote: Richard, what do you think?
I tend to agree that keeping defaults consistent is a good idea. I think that, subconsciously, the reason I designed the proposal the way I did was because I think the default of unqualified is wrong. But that's not a battle I wish to fight, and this kind of consistency has real merit. When I take a pass through the proposal to update it, I'll either add this (making unqualified the default for the new features) as a fleshed out alternative or incorporate it directly, depending on which would read more easily. Thanks, Richard

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.
But one thing jars with me:
* 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.
* In this proposal, the "qualified" convention is extended to data/class/..
declarations, and to module exports. That's all fine.
* 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.
Why the inconsistency here? Can't we use the "qualified" convention
everywhere? I think I would rather prefer to write
qualified module M (x,y) where ...
to make it clear that you have to refer to M.x qualified. That's a lot more
consistent with import statements.
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.
Cheers
Simon
On Wed, 14 Oct 2020 at 15:08, Spiwack, Arnaud
Dear all,
I would like to bring our own Richard Eisenberg’s proposal, #283: Local modules, to your attention. https://github.com/ghc-proposals/ghc-proposals/pull/283
The proposal is an attempt at solving the long debated issue that we can’t export qualified names out of a module (*e.g.* we may have to repeat import qualified Data.Map as Map and import qualified Data.Set as Set in every module in a project, rather than simply calling import MyPrelude 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.
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.
Some highlight (though do read the whole thing):
- We can define modules inside of other modules, with the syntax module Foo (some, optional, exports) where … - Like in the rest of Haskell, modules are no more than namespaces. Therefore you can open two module Foo, it will just merge the names in them - Values in local modules can be referred to, qualified, in the encompassing module - Local modules can be exported, importing them will import the name as qualified - A new import module Foo statement can be used in let and where clauses, it brings everything of the form Foo.x into scope unqualified for the scope of the let or where
Additionally, there is a small point that is not integral to the rest of the proposal, where defining, say, a type
data T = A | B
Would create a local module named T, such that the constructors could be referred to as T.A and T.B. I mention it separately, because it causes the only (small) backward incompatibility (that is Haskell 2010 programs which stop compiling when you turn on -XLocalModules).
I’m rather in favour of keeping it in, but it’s worth mentioning.
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.
/Arnaud _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

Hi, it seems that there are refinements possible. So even if most comments were supportive so far, shall we send it back to “needs revision” and discuss on the Github thread? Cheers, Joachim Am Freitag, den 16.10.2020, 10:03 +0100 schrieb Simon Marlow:
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.
But one thing jars with me:
* 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. * In this proposal, the "qualified" convention is extended to data/class/.. declarations, and to module exports. That's all fine. * 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.
Why the inconsistency here? Can't we use the "qualified" convention everywhere? I think I would rather prefer to write
qualified module M (x,y) where ...
to make it clear that you have to refer to M.x qualified. That's a lot more consistent with import statements.
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.
Cheers Simon
On Wed, 14 Oct 2020 at 15:08, Spiwack, Arnaud
wrote: Dear all,
I would like to bring our own Richard Eisenberg’s proposal, #283: Local modules, to your attention. https://github.com/ghc-proposals/ghc-proposals/pull/283
The proposal is an attempt at solving the long debated issue that we can’t export qualified names out of a module (e.g. we may have to repeat import qualified Data.Map as Map and import qualified Data.Set as Set in every module in a project, rather than simply calling import MyPrelude 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.
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.
Some highlight (though do read the whole thing):
We can define modules inside of other modules, with the syntax module Foo (some, optional, exports) where … Like in the rest of Haskell, modules are no more than namespaces. Therefore you can open two module Foo, it will just merge the names in them Values in local modules can be referred to, qualified, in the encompassing module Local modules can be exported, importing them will import the name as qualified A new import module Foo statement can be used in let and where clauses, it brings everything of the form Foo.x into scope unqualified for the scope of the let or where Additionally, there is a small point that is not integral to the rest of the proposal, where defining, say, a type
data T = A | B Would create a local module named T, such that the constructors could be referred to as T.A and T.B. I mention it separately, because it causes the only (small) backward incompatibility (that is Haskell 2010 programs which stop compiling when you turn on -XLocalModules).
I’m rather in favour of keeping it in, but it’s worth mentioning.
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.
/Arnaud
_______________________________________________ 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 -- Joachim Breitner mail@joachim-breitner.de http://www.joachim-breitner.de/

Yes. I've taken the liberty to mark this as Needs revision. I will revise to improve the clarity of the proposal. I do not expect any technical details to change. Richard
On Oct 27, 2020, at 1:59 PM, Joachim Breitner
wrote: Hi,
it seems that there are refinements possible. So even if most comments were supportive so far, shall we send it back to “needs revision” and discuss on the Github thread?
Cheers, Joachim
Am Freitag, den 16.10.2020, 10:03 +0100 schrieb Simon Marlow:
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.
But one thing jars with me:
* 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. * In this proposal, the "qualified" convention is extended to data/class/.. declarations, and to module exports. That's all fine. * 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.
Why the inconsistency here? Can't we use the "qualified" convention everywhere? I think I would rather prefer to write
qualified module M (x,y) where ...
to make it clear that you have to refer to M.x qualified. That's a lot more consistent with import statements.
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.
Cheers Simon
On Wed, 14 Oct 2020 at 15:08, Spiwack, Arnaud
wrote: Dear all,
I would like to bring our own Richard Eisenberg’s proposal, #283: Local modules, to your attention. https://github.com/ghc-proposals/ghc-proposals/pull/283
The proposal is an attempt at solving the long debated issue that we can’t export qualified names out of a module (e.g. we may have to repeat import qualified Data.Map as Map and import qualified Data.Set as Set in every module in a project, rather than simply calling import MyPrelude 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.
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.
Some highlight (though do read the whole thing):
We can define modules inside of other modules, with the syntax module Foo (some, optional, exports) where … Like in the rest of Haskell, modules are no more than namespaces. Therefore you can open two module Foo, it will just merge the names in them Values in local modules can be referred to, qualified, in the encompassing module Local modules can be exported, importing them will import the name as qualified A new import module Foo statement can be used in let and where clauses, it brings everything of the form Foo.x into scope unqualified for the scope of the let or where Additionally, there is a small point that is not integral to the rest of the proposal, where defining, say, a type
data T = A | B Would create a local module named T, such that the constructors could be referred to as T.A and T.B. I mention it separately, because it causes the only (small) backward incompatibility (that is Haskell 2010 programs which stop compiling when you turn on -XLocalModules).
I’m rather in favour of keeping it in, but it’s worth mentioning.
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.
/Arnaud
_______________________________________________ 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 -- 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
participants (5)
-
Alejandro Serrano Mena
-
Joachim Breitner
-
Richard Eisenberg
-
Simon Marlow
-
Spiwack, Arnaud