Hiding import behaviour
With the prelude changes that people have been discussing recently I've been wondering is there any reason why importing an identifier explicitly and unqualified doesn't automatically hide any implicit imports of the same identifier? Specifically I'm wondering about cases where you've imported an identifier explicitly from only one module, like this: module Foo (x, ...) where { ... } module Bar (x, ...) where { ... } import Bar import Foo (x) Even if you needed a pragma to enable it I can't think of any sensible reason why that shouldn't be equivalent to: import Bar hiding (x) import Foo (x) I don't know much of GHC's internals, but it seems like a pretty minimal change. Typing rules remain the same; explicit imports just shadow implicits. So importing multiple identifiers both implicitly or both explicitly would remain ambiguous. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
I think this is a great idea. I also think it should apply to the name shadowing warning—identifiers imported implicitly should never trigger that. On Thu, Oct 16, 2014 at 6:19 PM, Malcolm Gooding wrote: > With the prelude changes that people have been discussing recently > I've been wondering is there any reason why importing an identifier > explicitly and unqualified doesn't automatically hide any implicit > imports of the same identifier? Specifically I'm wondering about cases > where you've imported an identifier explicitly from only one module, > like this: > > module Foo (x, ...) where { ... } > module Bar (x, ...) where { ... } > > import Bar > import Foo (x) > > Even if you needed a pragma to enable it I can't think of any sensible > reason why that shouldn't be equivalent to: > > import Bar hiding (x) > import Foo (x) > > I don't know much of GHC's internals, but it seems like a pretty > minimal change. Typing rules remain the same; explicit imports just > shadow implicits. So importing multiple identifiers both implicitly or > both explicitly would remain ambiguous. > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users > ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
My first thought is: Wouldn't this make it impossible to reorder or sort imports lexicographically (or otherwise), without fully parsing, renaming and typechecking the code? For example, I often use ghc-mod plus stylish-haskell to order and format my imports. If there is no syntactic indication that one import should be hidden (and another preferred) as there is now, then reordering the imports of a working program willy-nilly could result in a program that no longer typechecks (or worse, one that does, but is now wrong). Maybe there are some cases today where something like this could happen, but this seems awfully, awfully implicit and hard-to-follow as a language feature. In general I think a program that has imports like this that may clash can be automated to make it easier to manage - but ultimately such imports tend to represent a complex relationship between a module and its dependencies - I'd prefer it if these were as clear as possible. On Thu, Oct 16, 2014 at 5:19 PM, Malcolm Gooding wrote: > With the prelude changes that people have been discussing recently > I've been wondering is there any reason why importing an identifier > explicitly and unqualified doesn't automatically hide any implicit > imports of the same identifier? Specifically I'm wondering about cases > where you've imported an identifier explicitly from only one module, > like this: > > module Foo (x, ...) where { ... } > module Bar (x, ...) where { ... } > > import Bar > import Foo (x) > > Even if you needed a pragma to enable it I can't think of any sensible > reason why that shouldn't be equivalent to: > > import Bar hiding (x) > import Foo (x) > > I don't know much of GHC's internals, but it seems like a pretty > minimal change. Typing rules remain the same; explicit imports just > shadow implicits. So importing multiple identifiers both implicitly or > both explicitly would remain ambiguous. > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users > -- Regards, Austin Seipp, Haskell Consultant Well-Typed LLP, http://www.well-typed.com/ ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
Well I suppose tooling might need to be aware of the feature depending on what it does, but I don't see why the code actually typechecking would need to be dependent on ordering. When I say shadowing I don't mean explicitly having any explicit import create a new scope, since in that case it would be sensitive to re-ordering, which I agree would be bad. My thought would be first you would need to parse all the imports to see which identifiers they import, then do another pass to change the imports to hide any identifiers that should be shadowed. So in the example I gave you would need to be aware that Foo exports x, because otherwise there would be no way to know that x needs to be hidden from Bar. I assume GHC already would have access to that information though. -- View this message in context: http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758161.html Sent from the Haskell - Glasgow-haskell-users mailing list archive at Nabble.com. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
It should be good enough (for what you're talking about) to hide them all. Turn import A (foo) import B (bar) import C hiding (baz) import D into import A (foo) import B (bar) import C hiding (foo,bar,baz) import D hiding (foo,bar) There's no reason to worry about hiding nonexistent identifiers, I don't think. On Thu, Oct 16, 2014 at 7:10 PM, htebalaka wrote: > Well I suppose tooling might need to be aware of the feature depending on > what it does, but I don't see why the code actually typechecking would need > to be dependent on ordering. When I say shadowing I don't mean explicitly > having any explicit import create a new scope, since in that case it would > be sensitive to re-ordering, which I agree would be bad. My thought would > be > first you would need to parse all the imports to see which identifiers they > import, then do another pass to change the imports to hide any identifiers > that should be shadowed. > > So in the example I gave you would need to be aware that Foo exports x, > because otherwise there would be no way to know that x needs to be hidden > from Bar. I assume GHC already would have access to that information > though. > > > > -- > View this message in context: > http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758161.html > Sent from the Haskell - Glasgow-haskell-users mailing list archive at > Nabble.com. > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users > ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
Yeah, I just realized that would work too. You would still need to do two passes over the imports, so foo and bar are hidden from anything imported above A. Though while we're reasoning syntactically, you would also need to hide them from the Prelude if it was being implicitly imported. -- View this message in context: http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758166.html Sent from the Haskell - Glasgow-haskell-users mailing list archive at Nabble.com. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
-BEGIN PGP SIGNED MESSAGE- Hash: SHA256 On 17/10/14 00:40, Austin Seipp wrote: > Maybe there are some cases today where something like this could > happen, but this seems awfully, awfully implicit and hard-to-follow > as a language feature. > > In general I think a program that has imports like this that may > clash can be automated to make it easier to manage - but ultimately > such imports tend to represent a complex relationship between a > module and its dependencies - I'd prefer it if these were as clear > as possible. Very strong +1 from me. It seems awfully implicit and obscure for very little benefit, and it may mean quite a bit of work for tool developers. - -- Alexander alexan...@plaimi.net https://secure.plaimi.net/~alexander -BEGIN PGP SIGNATURE- Version: GnuPG v2 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iF4EAREIAAYFAlRAxf8ACgkQRtClrXBQc7WGewD/Vt/7OdyPgzORiE4uHtU/p22a TLGGnQuceSlrMJiWFhMA/0GuZ1leom0ILvrqW/oJYugnwGgX1atqmneJoZ72qNEM =+oUV -END PGP SIGNATURE- ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
On 10/17/14 12:32, Alexander Berntsen wrote: > On 17/10/14 00:40, Austin Seipp wrote: > > Maybe there are some cases today where something like this could > > happen, but this seems awfully, awfully implicit and hard-to-follow > > as a language feature. > > > > In general I think a program that has imports like this that may > > clash can be automated to make it easier to manage - but ultimately > > such imports tend to represent a complex relationship between a > > module and its dependencies - I'd prefer it if these were as clear > > as possible. > Very strong +1 from me. It seems awfully implicit and obscure for very > little benefit, and it may mean quite a bit of work for tool developers. I guess my central point is I don't see how anyone can benefit from the current behaviour. For instance, a simple real world example: import Prelude import Data.Text.Lazy.IO (putStrLn) Regardless of the ordering of the imports, is there any way for me to use putStrLn in any context without hiding it from the Prelude (and any other modules that I might be unintentionally importing it from)? Any unqualified use will be ambiguous, unless you hide it from every other module that might export a function with the same name. I would think the fact that it shouldn't be implicitly imported from other modules would directly follow from the fact you imported it explicitly (otherwise, why did you import it?). I'm having trouble coming up with a single example where the current behaviour is useful. I can't speak to tooling, though I suppose if this doesn't get implemented I'll write my own. Just to be very clear, supposing you have some Import datatype which stores a list of any identifiers that are being explicitly imported unqualified (or conversely, a list of any identifiers that are being hidden), then the behaviour I'm suggesting is a pragma to enable something like this: hide :: [Import] -> [Import] hide = flip (fmap fmap appendHiddenImports) <*> collectOnly where collectOnly :: [Import] -> [Identifier] collectOnly = concat . mapMaybe getExplicitImports appendHiddenImports :: [Identifier] -> Import -> Import getExplicitImports :: Import -> Maybe [Identifier] where appendHiddenImports would only change import statements that import an unspecified number of unqualified identifiers, like "import X hiding (x, y)" or "import Y". -- View this message in context: http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758246.html Sent from the Haskell - Glasgow-haskell-users mailing list archive at Nabble.com. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
You mention only unqualified imports, but if we do this, it should also apply to qualified ones: import qualified Data.List as L import qualified MyModule as L (isInfixOf) On Oct 18, 2014 2:02 PM, "htebalaka" wrote: > On 10/17/14 12:32, Alexander Berntsen wrote: > > On 17/10/14 00:40, Austin Seipp wrote: > > > Maybe there are some cases today where something like this could > > > happen, but this seems awfully, awfully implicit and hard-to-follow > > > as a language feature. > > > > > > In general I think a program that has imports like this that may > > > clash can be automated to make it easier to manage - but ultimately > > > such imports tend to represent a complex relationship between a > > > module and its dependencies - I'd prefer it if these were as clear > > > as possible. > > Very strong +1 from me. It seems awfully implicit and obscure for very > > little benefit, and it may mean quite a bit of work for tool developers. > > I guess my central point is I don't see how anyone can benefit from the > current behaviour. For instance, a simple real world example: > > import Prelude > import Data.Text.Lazy.IO (putStrLn) > > Regardless of the ordering of the imports, is there any way for me to use > putStrLn in any context without hiding it from the Prelude (and any other > modules that I might be unintentionally importing it from)? Any unqualified > use will be ambiguous, unless you hide it from every other module that > might > export a function with the same name. I would think the fact that it > shouldn't be implicitly imported from other modules would directly follow > from the fact you imported it explicitly (otherwise, why did you import > it?). I'm having trouble coming up with a single example where the current > behaviour is useful. > > I can't speak to tooling, though I suppose if this doesn't get implemented > I'll write my own. Just to be very clear, supposing you have some Import > datatype which stores a list of any identifiers that are being explicitly > imported unqualified (or conversely, a list of any identifiers that are > being hidden), then the behaviour I'm suggesting is a pragma to enable > something like this: > > hide :: [Import] -> [Import] > hide = flip (fmap fmap appendHiddenImports) <*> collectOnly where > collectOnly :: [Import] -> [Identifier] > collectOnly = concat . mapMaybe getExplicitImports > appendHiddenImports :: [Identifier] -> Import -> Import > getExplicitImports :: Import -> Maybe [Identifier] > > where appendHiddenImports would only change import statements that import > an > unspecified number of unqualified identifiers, like "import X hiding (x, > y)" > or "import Y". > > > > -- > View this message in context: > http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758246.html > Sent from the Haskell - Glasgow-haskell-users mailing list archive at > Nabble.com. > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users > ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
[Import] > hide = flip (fmap fmap appendHiddenImports) <*> collectOnly where > collectOnly :: [Import] -> [Identifier] > collectOnly = concat . mapMaybe getExplicitImports > appendHiddenImports :: [Identifier] -> Import -> Import > getExplicitImports :: Import -> Maybe [Identifier] > > where appendHiddenImports would only change import statements that import an > unspecified number of unqualified identifiers, like "import X hiding (x, y)" > or "import Y". > > > > -- > View this message in context: > http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758246.html > Sent from the Haskell - Glasgow-haskell-users mailing list archive at > Nabble.com. > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users > -- Regards, Austin Seipp, Haskell Consultant Well-Typed LLP, http://www.well-typed.com/ ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
This all just seems like a relatively large amount of hoops to jump > through, just to avoid writing 'hiding' in a on a few things, so to > me, the cure looks worse than the disease. But I may just be missing > something completely. > >> Any unqualified use will be ambiguous, unless you hide it from every other >> module that might >> export a function with the same name. I would think the fact that it >> shouldn't be implicitly imported from other modules would directly follow >> from the fact you imported it explicitly (otherwise, why did you import >> it?). I'm having trouble coming up with a single example where the current >> behaviour is useful. >> >> I can't speak to tooling, though I suppose if this doesn't get implemented >> I'll write my own. Just to be very clear, supposing you have some Import >> datatype which stores a list of any identifiers that are being explicitly >> imported unqualified (or conversely, a list of any identifiers that are >> being hidden), then the behaviour I'm suggesting is a pragma to enable >> something like this: >> >> hide :: [Import] -> [Import] >> hide = flip (fmap fmap appendHiddenImports) <*> collectOnly where >> collectOnly :: [Import] -> [Identifier] >> collectOnly = concat . mapMaybe getExplicitImports >> appendHiddenImports :: [Identifier] -> Import -> Import >> getExplicitImports :: Import -> Maybe [Identifier] >> >> where appendHiddenImports would only change import statements that import an >> unspecified number of unqualified identifiers, like "import X hiding (x, y)" >> or "import Y". >> >> >> >> -- >> View this message in context: >> http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758246.html >> Sent from the Haskell - Glasgow-haskell-users mailing list archive at >> Nabble.com. >> ___ >> Glasgow-haskell-users mailing list >> Glasgow-haskell-users@haskell.org >> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users >> > > -- > Regards, > > Austin Seipp, Haskell Consultant > Well-Typed LLP, http://www.well-typed.com/ -- Regards, Austin Seipp, Haskell Consultant Well-Typed LLP, http://www.well-typed.com/ ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
I don't normally import things qualified like that, so it hadn't occurred to me, but that makes sense. I do want to be clear that this shouldn't be sensitive to ordering, and it can occur before type checking. You just need to know what modules are importing which identifiers explicitly, and what modules are importing an unspecified set of identifiers. It should be possible to do while parsing even, as soon as you've reached a point where you know every import statement has been reached. The behaviour would thus remain the same if someone was to explicitly import the same identifier from two or more modules, since hiding the implicit imports wouldn't remove the ambiguity in that case. I'm pretty sure the code I provided is sufficient; you would just need a separate pass for qualified and unqualified imports. David Feuer wrote > You mention only unqualified imports, but if we do this, it should also > apply to qualified ones: > > import qualified Data.List as L > import qualified MyModule as L (isInfixOf) > On Oct 18, 2014 2:02 PM, "htebalaka" < > goodingm@ > > wrote: > >> On 10/17/14 12:32, Alexander Berntsen wrote: >> > On 17/10/14 00:40, Austin Seipp wrote: >> > > Maybe there are some cases today where something like this could >> > > happen, but this seems awfully, awfully implicit and hard-to-follow >> > > as a language feature. >> > > >> > > In general I think a program that has imports like this that may >> > > clash can be automated to make it easier to manage - but ultimately >> > > such imports tend to represent a complex relationship between a >> > > module and its dependencies - I'd prefer it if these were as clear >> > > as possible. >> > Very strong +1 from me. It seems awfully implicit and obscure for very >> > little benefit, and it may mean quite a bit of work for tool >> developers. >> >> I guess my central point is I don't see how anyone can benefit from the >> current behaviour. For instance, a simple real world example: >> >> import Prelude >> import Data.Text.Lazy.IO (putStrLn) >> >> Regardless of the ordering of the imports, is there any way for me to use >> putStrLn in any context without hiding it from the Prelude (and any other >> modules that I might be unintentionally importing it from)? Any >> unqualified >> use will be ambiguous, unless you hide it from every other module that >> might >> export a function with the same name. I would think the fact that it >> shouldn't be implicitly imported from other modules would directly follow >> from the fact you imported it explicitly (otherwise, why did you import >> it?). I'm having trouble coming up with a single example where the >> current >> behaviour is useful. >> >> I can't speak to tooling, though I suppose if this doesn't get >> implemented >> I'll write my own. Just to be very clear, supposing you have some Import >> datatype which stores a list of any identifiers that are being explicitly >> imported unqualified (or conversely, a list of any identifiers that are >> being hidden), then the behaviour I'm suggesting is a pragma to enable >> something like this: >> >> hide :: [Import] -> [Import] >> hide = flip (fmap fmap appendHiddenImports) <*> collectOnly where >> collectOnly :: [Import] -> [Identifier] >> collectOnly = concat . mapMaybe getExplicitImports >> appendHiddenImports :: [Identifier] -> Import -> Import >> getExplicitImports :: Import -> Maybe [Identifier] >> >> where appendHiddenImports would only change import statements that import >> an >> unspecified number of unqualified identifiers, like "import X hiding (x, >> y)" >> or "import Y". >> >> >> >> -- >> View this message in context: >> http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758246.html >> Sent from the Haskell - Glasgow-haskell-users mailing list archive at >> Nabble.com. >> ___ >> Glasgow-haskell-users mailing list >> > Glasgow-haskell-users@ >> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users >> > > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@ > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users -- View this message in context: http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758251.html Sent from the Haskell - Glasgow-haskell-users mailing list archive at Nabble.com. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
speak, where with >> 'hiding', order no longer matters in the import list. >> >> Of course you might say, "Well, of course Prelude exports putStrLn, so >> you wouldn't move the import, and it wouldn't be a problem". The >> problem is I don't know what exports an arbitrary module has; it >> doesn't seem to scale mentally for humans at all. In this case, I know >> Prelude exports that, but in the general case of: >> >> import Frob >> import Knob (xyz) >> >> Today, this means I only import 'xyz' from Knob, and there are no >> other ambiguous names. But under your proposal, I have zero clue if >> 'xyz' is actually shadowing a prior import. So unless I check *all* >> the transitive exports of 'Frob', I have no clue if it's actually safe >> to move the import of 'Knob' higher up - an identifier may not be >> shadowed if I do that. OTOH, I know *for a fact* when I see this: >> >> import Frob hiding (xyz) >> import Knob (xyz) >> >> which 'xyz' I'm referring to later, without ambiguity. Also, what >> happens if I do this: >> >> import Knob (xyz) >> import Frob >> >> legitimately, without shadowing, and 'Frob' later ends up exporting >> its own 'xyz'? Do I just get an ambiguous identifier error, like I >> would today? Again, shadowing in this sense only works 'one-way': top >> to bottom, and it fails any other case they might be rearranged. >> >> This all just seems like a relatively large amount of hoops to jump >> through, just to avoid writing 'hiding' in a on a few things, so to >> me, the cure looks worse than the disease. But I may just be missing >> something completely. >> >>> Any unqualified use will be ambiguous, unless you hide it from every >>> other module that might >>> export a function with the same name. I would think the fact that it >>> shouldn't be implicitly imported from other modules would directly >>> follow >>> from the fact you imported it explicitly (otherwise, why did you import >>> it?). I'm having trouble coming up with a single example where the >>> current >>> behaviour is useful. >>> >>> I can't speak to tooling, though I suppose if this doesn't get >>> implemented >>> I'll write my own. Just to be very clear, supposing you have some Import >>> datatype which stores a list of any identifiers that are being >>> explicitly >>> imported unqualified (or conversely, a list of any identifiers that are >>> being hidden), then the behaviour I'm suggesting is a pragma to enable >>> something like this: >>> >>> hide :: [Import] -> [Import] >>> hide = flip (fmap fmap appendHiddenImports) <*> collectOnly where >>> collectOnly :: [Import] -> [Identifier] >>> collectOnly = concat . mapMaybe getExplicitImports >>> appendHiddenImports :: [Identifier] -> Import -> Import >>> getExplicitImports :: Import -> Maybe [Identifier] >>> >>> where appendHiddenImports would only change import statements that >>> import an >>> unspecified number of unqualified identifiers, like "import X hiding (x, >>> y)" >>> or "import Y". >>> >>> >>> >>> -- >>> View this message in context: >>> http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758246.html >>> Sent from the Haskell - Glasgow-haskell-users mailing list archive at >>> Nabble.com. >>> ___ >>> Glasgow-haskell-users mailing list >>> > Glasgow-haskell-users@ >>> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users >>> >> >> -- >> Regards, >> >> Austin Seipp, Haskell Consultant >> Well-Typed LLP, http://www.well-typed.com/ > > > > -- > Regards, > > Austin Seipp, Haskell Consultant > Well-Typed LLP, http://www.well-typed.com/ > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@ > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users -- View this message in context: http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758254.html Sent from the Haskell - Glasgow-haskell-users mailing list archive at Nabble.com. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
; use >>>> putStrLn in any context without hiding it from the Prelude (and any >>>> other >>>> modules that I might be unintentionally importing it from)? >>> >>> I suppose my point isn't that the current behavior is more useful, but >>> the *proposed behavior seems more confusing for humans*. I would >>> rather have GHC inform me of an ambiguous import as opposed to >>> silently accepting or rejecting my program based on the import list, >>> and whether it shadows something prior to it. I don't even always know >>> what identifiers may get imported in the first place, due to >>> transitive module reexports. It just seems like pretty confusing >>> behavior - shadowing of identifiers is rarely a 'feature' for humans, >>> IMO. >>> >>> In the example you have, what happens if I change the import list of >>> Data.Text by removing it, for example, or what happens if I *remove* >>> the Prelude import, and stick it after the Text import? Rather than >>> getting an out of scope identifier error, or something ambiguous, I'd >>> get a confusing type error based on Prelude's use of putStrLn in the >>> context of needing Texts', because the shadowing would fail to apply >>> since it didn't occur before the Text import. Shadowing of previously >>> imported identifiers only works one-way, so to speak, where with >>> 'hiding', order no longer matters in the import list. >>> >>> Of course you might say, "Well, of course Prelude exports putStrLn, so >>> you wouldn't move the import, and it wouldn't be a problem". The >>> problem is I don't know what exports an arbitrary module has; it >>> doesn't seem to scale mentally for humans at all. In this case, I know >>> Prelude exports that, but in the general case of: >>> >>> import Frob >>> import Knob (xyz) >>> >>> Today, this means I only import 'xyz' from Knob, and there are no >>> other ambiguous names. But under your proposal, I have zero clue if >>> 'xyz' is actually shadowing a prior import. So unless I check *all* >>> the transitive exports of 'Frob', I have no clue if it's actually safe >>> to move the import of 'Knob' higher up - an identifier may not be >>> shadowed if I do that. OTOH, I know *for a fact* when I see this: >>> >>> import Frob hiding (xyz) >>> import Knob (xyz) >>> >>> which 'xyz' I'm referring to later, without ambiguity. Also, what >>> happens if I do this: >>> >>> import Knob (xyz) >>> import Frob >>> >>> legitimately, without shadowing, and 'Frob' later ends up exporting >>> its own 'xyz'? Do I just get an ambiguous identifier error, like I >>> would today? Again, shadowing in this sense only works 'one-way': top >>> to bottom, and it fails any other case they might be rearranged. >>> >>> This all just seems like a relatively large amount of hoops to jump >>> through, just to avoid writing 'hiding' in a on a few things, so to >>> me, the cure looks worse than the disease. But I may just be missing >>> something completely. >>> >>>> Any unqualified use will be ambiguous, unless you hide it from every >>>> other module that might >>>> export a function with the same name. I would think the fact that it >>>> shouldn't be implicitly imported from other modules would directly >>>> follow >>>> from the fact you imported it explicitly (otherwise, why did you import >>>> it?). I'm having trouble coming up with a single example where the >>>> current >>>> behaviour is useful. >>>> >>>> I can't speak to tooling, though I suppose if this doesn't get >>>> implemented >>>> I'll write my own. Just to be very clear, supposing you have some >>>> Import >>>> datatype which stores a list of any identifiers that are being >>>> explicitly >>>> imported unqualified (or conversely, a list of any identifiers that are >>>> being hidden), then the behaviour I'm suggesting is a pragma to enable >>>> something like this: >>>> >>>> hide :: [Import] -> [Import] >>>> hide = flip (fmap fmap appendHiddenImports) <*> collectOnly where >>>> collectOnly :: [Import] -> [Identifier] >>>> collectOnly = concat . mapMaybe getExplicitImports >>>> appendHiddenImports :: [Identifier] -> Import -> Import >>>> getExplicitImports :: Import -> Maybe [Identifier] >>>> >>>> where appendHiddenImports would only change import statements that >>>> import an >>>> unspecified number of unqualified identifiers, like "import X hiding >>>> (x, y)" >>>> or "import Y". >>>> >>>> >>>> >>>> -- >>>> View this message in context: >>>> http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758246.html >>>> Sent from the Haskell - Glasgow-haskell-users mailing list archive at >>>> Nabble.com. >>>> ___ >>>> Glasgow-haskell-users mailing list >>>> >> Glasgow-haskell-users@ >>>> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users >>>> >>> >>> -- >>> Regards, >>> >>> Austin Seipp, Haskell Consultant >>> Well-Typed LLP, http://www.well-typed.com/ >> >> >> >> -- >> Regards, >> >> Austin Seipp, Haskell Consultant >> Well-Typed LLP, http://www.well-typed.com/ >> ___ >> Glasgow-haskell-users mailing list >> Glasgow-haskell-users@ >> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users -- View this message in context: http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758257.html Sent from the Haskell - Glasgow-haskell-users mailing list archive at Nabble.com. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
Hi, Am Samstag, den 18.10.2014, 11:02 -0700 schrieb htebalaka: > I guess my central point is I don't see how anyone can benefit from the > current behaviour. For instance, a simple real world example: > > import Prelude > import Data.Text.Lazy.IO (putStrLn) I find this quite convincing. If I bother to explicitly write out „take putStrLn from Data.Text.Lazy.IO“, why should the compiler assume that I might have meant some putStrLn from somewhere else. Of course, order should not matter (I don’t think anyone suggested it should, I think Austin simply mis-read that). Greetings, Joachim -- Joachim “nomeata” Breitner m...@joachim-breitner.de • http://www.joachim-breitner.de/ Jabber: nome...@joachim-breitner.de • GPG-Key: 0xF0FBF51F Debian Developer: nome...@debian.org signature.asc Description: This is a digitally signed message part ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
I'm generally in favor of the proposal, but I figured I should mention one situation when I personally might find this confusing. If the module import list is very long, and includes an unrestricted import of a well-known module, it might be easy to assume a certain well-known function comes from there, when in fact it comes from some other module on the other end of the import list. On Oct 18, 2014 6:39 PM, "Joachim Breitner" wrote: > Hi, > > Am Samstag, den 18.10.2014, 11:02 -0700 schrieb htebalaka: > > I guess my central point is I don't see how anyone can benefit from the > > current behaviour. For instance, a simple real world example: > > > > import Prelude > > import Data.Text.Lazy.IO (putStrLn) > > I find this quite convincing. If I bother to explicitly write out „take > putStrLn from Data.Text.Lazy.IO“, why should the compiler assume that I > might have meant some putStrLn from somewhere else. > > Of course, order should not matter (I don’t think anyone suggested it > should, I think Austin simply mis-read that). > > Greetings, > Joachim > > > -- > Joachim “nomeata” Breitner > m...@joachim-breitner.de • http://www.joachim-breitner.de/ > Jabber: nome...@joachim-breitner.de • GPG-Key: 0xF0FBF51F > Debian Developer: nome...@debian.org > > > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users > > ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
On 2014-10-19 at 00:39:42 +0200, Joachim Breitner wrote: >> I guess my central point is I don't see how anyone can benefit from the >> current behaviour. For instance, a simple real world example: >> >> import Prelude >> import Data.Text.Lazy.IO (putStrLn) > > I find this quite convincing. If I bother to explicitly write out „take > putStrLn from Data.Text.Lazy.IO“, why should the compiler assume that I > might have meant some putStrLn from somewhere else. I think we've reached the point where this proposal should be turned into a Wiki page detailing the exact semantics[1], and giving this extension a catchy name... If it's trivial enough (in the sense there is little design-space variation to get it wrong), having it in 7.10 rather than 7.12 may be still possible (and IMHO desirable to be able to start using it earlier rather than later on real-world code). [1]: Cases to consider include all combinations of variations of import-statements; as well as turning most unqualified imports from which entities are to be hidden into a pair of qualified and unqualified import: import Doo (doo) import Bar -- provide 'doo' as well which I'd think should be transformed into import Doo (doo) import qualified Bar import Bar hiding (doo) as to allow to still have 'Bar.doo' in scope (unless some other import explicitly mentions `... as Bar (doo)`, in which case that needs to be hidden from the qualified `Bar` import as well) Cheers, hvr ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
I feel that this extension, while looking tempting for writing code from scratch, might hurt maintainability of code. Adding an explicit import can suddenly cause type errors in completely unrelated places (when it hides an implicit import and the new function is type incorrect), or worse, can cause semantic change (when it hides an implicit import and the new function is type correct, but has different behavior). Remember that not all code is written by the same person, or in a short time frame, so not everybody might fully understand every module and every import of the code they're editing. Erik On Sun, Oct 19, 2014 at 1:32 AM, David Feuer wrote: > I'm generally in favor of the proposal, but I figured I should mention one > situation when I personally might find this confusing. If the module import > list is very long, and includes an unrestricted import of a well-known > module, it might be easy to assume a certain well-known function comes from > there, when in fact it comes from some other module on the other end of the > import list. > > On Oct 18, 2014 6:39 PM, "Joachim Breitner" > wrote: >> >> Hi, >> >> Am Samstag, den 18.10.2014, 11:02 -0700 schrieb htebalaka: >> > I guess my central point is I don't see how anyone can benefit from the >> > current behaviour. For instance, a simple real world example: >> > >> > import Prelude >> > import Data.Text.Lazy.IO (putStrLn) >> >> I find this quite convincing. If I bother to explicitly write out „take >> putStrLn from Data.Text.Lazy.IO“, why should the compiler assume that I >> might have meant some putStrLn from somewhere else. >> >> Of course, order should not matter (I don’t think anyone suggested it >> should, I think Austin simply mis-read that). >> >> Greetings, >> Joachim >> >> >> -- >> Joachim “nomeata” Breitner >> m...@joachim-breitner.de • http://www.joachim-breitner.de/ >> Jabber: nome...@joachim-breitner.de • GPG-Key: 0xF0FBF51F >> Debian Developer: nome...@debian.org >> >> >> ___ >> Glasgow-haskell-users mailing list >> Glasgow-haskell-users@haskell.org >> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users >> > > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users > ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
At least in the case where something being hidden causes an unintended type error, compiler errors could /potentially/ be aware of the extension, though defining unintended seems non-trivial. You don't want actual type errors being replaced with "maybe you didn't realize this other function is being auto-hidden", and you definitely don't want to have to type check for different combination of hidden functions. I don't think it's really worth extending the scope, unless there's some trivial solution I'm missing. What I want to be able to do is use a not-too-large set of more general (IO -> MonadIO) or differently monomorphic (String -> Text) functions than what I'm implicitly importing. In either case I think the change is semantically safe: any type errors you encounter are actual type errors. This should make that kind of use a little more lightweight than it is currently. I'll definitely concede it could be unsuitable behaviour by default for large projects. My coding is mostly personal-use stuff, so that's where my experience is. Is there a good example proposal somewhere for what kind of format I should follow. I'm somewhat busy at the moment, but I'll write up a more detailed proposal on the wiki by the end of the week unless someone feels compelled to beat me to it. Erik Hesselink wrote > I feel that this extension, while looking tempting for writing code > from scratch, might hurt maintainability of code. Adding an explicit > import can suddenly cause type errors in completely unrelated places > (when it hides an implicit import and the new function is type > incorrect), or worse, can cause semantic change (when it hides an > implicit import and the new function is type correct, but has > different behavior). Remember that not all code is written by the same > person, or in a short time frame, so not everybody might fully > understand every module and every import of the code they're editing. > > Erik > > On Sun, Oct 19, 2014 at 1:32 AM, David Feuer < > david.feuer@ > > wrote: >> I'm generally in favor of the proposal, but I figured I should mention >> one >> situation when I personally might find this confusing. If the module >> import >> list is very long, and includes an unrestricted import of a well-known >> module, it might be easy to assume a certain well-known function comes >> from >> there, when in fact it comes from some other module on the other end of >> the >> import list. >> >> On Oct 18, 2014 6:39 PM, "Joachim Breitner" < > mail@ > > >> wrote: >>> >>> Hi, >>> >>> Am Samstag, den 18.10.2014, 11:02 -0700 schrieb htebalaka: >>> > I guess my central point is I don't see how anyone can benefit from >>> the >>> > current behaviour. For instance, a simple real world example: >>> > >>> > import Prelude >>> > import Data.Text.Lazy.IO (putStrLn) >>> >>> I find this quite convincing. If I bother to explicitly write out „take >>> putStrLn from Data.Text.Lazy.IO“, why should the compiler assume that I >>> might have meant some putStrLn from somewhere else. >>> >>> Of course, order should not matter (I don’t think anyone suggested it >>> should, I think Austin simply mis-read that). >>> >>> Greetings, >>> Joachim >>> >>> >>> -- >>> Joachim “nomeata” Breitner >>> > mail@ > • http://www.joachim-breitner.de/ >>> Jabber: > nomeata@ > • GPG-Key: 0xF0FBF51F >>> Debian Developer: > nomeata@ >>> >>> >>> ___ >>> Glasgow-haskell-users mailing list >>> > Glasgow-haskell-users@ >>> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users >>> >> >> ___ >> Glasgow-haskell-users mailing list >> > Glasgow-haskell-users@ >> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users >> > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@ > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users -- View this message in context: http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758327.html Sent from the Haskell - Glasgow-haskell-users mailing list archive at Nabble.com. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
think anyone suggested it >>>> should, I think Austin simply mis-read that). >>>> >>>> Greetings, >>>> Joachim >>>> >>>> >>>> -- >>>> Joachim “nomeata” Breitner >>>> >> mail@ >> • http://www.joachim-breitner.de/ >>>> Jabber: >> nomeata@ >> • GPG-Key: 0xF0FBF51F >>>> Debian Developer: >> nomeata@ >>>> >>>> >>>> ___ >>>> Glasgow-haskell-users mailing list >>>> >> Glasgow-haskell-users@ >>>> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users >>>> >>> >>> ___ >>> Glasgow-haskell-users mailing list >>> >> Glasgow-haskell-users@ >>> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users >>> >> ___ >> Glasgow-haskell-users mailing list >> Glasgow-haskell-users@ >> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users -- View this message in context: http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758346.html Sent from the Haskell - Glasgow-haskell-users mailing list archive at Nabble.com. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
On 14-10-19 08:10 AM, Erik Hesselink wrote: I feel that this extension, while looking tempting for writing code from scratch, might hurt maintainability of code. That depends on how you define maintainability. Adding an explicit import can suddenly cause type errors in completely unrelated places (when it hides an implicit import and the new function is type incorrect), or worse, can cause semantic change (when it hides an implicit import and the new function is type correct, but has different behavior). Remember that not all code is written by the same person, or in a short time frame, so not everybody might fully understand every module and every import of the code they're editing. Your example requires somebody actively editing the import list. A code change causes a compile error or worse? That is not all that surprising. No, what I find much worse is a cabal update causing an error in a module that was correct before the update. Consider > module Main where > > import Foo (foo) > import Bar > > main = foo Now suppose Bar came from the package bar-1.0, and the new version bar-1.0.1 decides to export foo. With the current behaviour, this change would break my module. With Malcolm's proposal the old code would continue to work. Anyway, count me as +1 on the proposal. It would improve the long-term stability of Haskell code. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
On Mon, Oct 20, 2014 at 11:57 PM, Mario Blažević wrote: > On 14-10-19 08:10 AM, Erik Hesselink wrote: >> >> Adding an explicit >> import can suddenly cause type errors in completely unrelated places >> (when it hides an implicit import and the new function is type >> incorrect), or worse, can cause semantic change (when it hides an >> implicit import and the new function is type correct, but has >> different behavior). Remember that not all code is written by the same >> person, or in a short time frame, so not everybody might fully >> understand every module and every import of the code they're editing. > > Your example requires somebody actively editing the import list. A > code change causes a compile error or worse? That is not all that > surprising. But right now, we have a useful property that adding imports and code to a module does not break or change other code in that module. With this extension, that changes. I find this kind of local reasoning very useful, IMHO it's one of the most useful things about Haskell in general. > No, what I find much worse is a cabal update causing an error in a > module that was correct before the update. Consider > >> module Main where >> >> import Foo (foo) >> import Bar >> >> main = foo > > Now suppose Bar came from the package bar-1.0, and the new version > bar-1.0.1 decides to export foo. With the current behaviour, this change > would break my module. With Malcolm's proposal the old code would continue > to work. That's a very good point. Given that and the above, I don't understand your conclusion: > Anyway, count me as +1 on the proposal. It would improve the > long-term stability of Haskell code. How is adding more ways to break something "improving the long-term stability"? Regards, Erik ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
I'm having a hard time keeping track of what's going on in this discussion. But, I'm generally in favor of making *some* change along the lines discussed here, and also in #9702 (https://ghc.haskell.org/trac/ghc/ticket/9702). Could the proposers of various features perhaps create a wiki page, naming the individual pieces or proposals, and then we can have something closer to a vote among a stable list of candidates? Thanks! Richard On Oct 21, 2014, at 7:14 AM, Erik Hesselink wrote: > On Mon, Oct 20, 2014 at 11:57 PM, Mario Blažević wrote: >> On 14-10-19 08:10 AM, Erik Hesselink wrote: >>> >>> Adding an explicit >>> import can suddenly cause type errors in completely unrelated places >>> (when it hides an implicit import and the new function is type >>> incorrect), or worse, can cause semantic change (when it hides an >>> implicit import and the new function is type correct, but has >>> different behavior). Remember that not all code is written by the same >>> person, or in a short time frame, so not everybody might fully >>> understand every module and every import of the code they're editing. >> >>Your example requires somebody actively editing the import list. A >> code change causes a compile error or worse? That is not all that >> surprising. > > But right now, we have a useful property that adding imports and code > to a module does not break or change other code in that module. With > this extension, that changes. I find this kind of local reasoning very > useful, IMHO it's one of the most useful things about Haskell in > general. > >>No, what I find much worse is a cabal update causing an error in a >> module that was correct before the update. Consider >> >>> module Main where >>> >>> import Foo (foo) >>> import Bar >>> >>> main = foo >> >>Now suppose Bar came from the package bar-1.0, and the new version >> bar-1.0.1 decides to export foo. With the current behaviour, this change >> would break my module. With Malcolm's proposal the old code would continue >> to work. > > That's a very good point. Given that and the above, I don't understand > your conclusion: > >>Anyway, count me as +1 on the proposal. It would improve the >> long-term stability of Haskell code. > > How is adding more ways to break something "improving the long-term > stability"? > > Regards, > > Erik > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users > ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
Hi Erik, > But right now, we have a useful property that adding imports and code > to a module does not break or change other code in that module. With > this extension, that changes. So your biggest concern is about silent breakage of code, that suddenly a different function is used which has the same name and type, but different semantics. In all other cases the compiler would throw an error, because the types wouldn't match. I have the feeling, that the proposal shouldn't be about implicit/explicit imports, but about prefering the function with the fitting type. If there're two functions with the same name and type in scope, then the compiler most likely should always throw an error. The only exception might be, if there's a function locally defined in the module, then this one might be prefered over every imported one with the same name and type. But perhaps even in this case it might be a good idea to throw an error. Greetings, Daniel ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
On 14-10-21 07:14 AM, Erik Hesselink wrote: On Mon, Oct 20, 2014 at 11:57 PM, Mario Blažević wrote: On 14-10-19 08:10 AM, Erik Hesselink wrote: Adding an explicit import can suddenly cause type errors in completely unrelated places (when it hides an implicit import and the new function is type incorrect), or worse, can cause semantic change (when it hides an implicit import and the new function is type correct, but has different behavior). Remember that not all code is written by the same person, or in a short time frame, so not everybody might fully understand every module and every import of the code they're editing. Your example requires somebody actively editing the import list. A code change causes a compile error or worse? That is not all that surprising. But right now, we have a useful property that adding imports and code to a module does not break or change other code in that module. With this extension, that changes. I find this kind of local reasoning very useful, IMHO it's one of the most useful things about Haskell in general. Right now, adding an import can certainly cause a compiler error. It can't change the run-time behaviour of a correct module, that is true. With the proposal, there would be still be a somewhat weaker guarantee: adding an *implicit* import would never change the module's run-time behaviour. No, what I find much worse is a cabal update causing an error in a module that was correct before the update. Consider module Main where import Foo (foo) import Bar main = foo Now suppose Bar came from the package bar-1.0, and the new version bar-1.0.1 decides to export foo. With the current behaviour, this change would break my module. With Malcolm's proposal the old code would continue to work. That's a very good point. Given that and the above, I don't understand your conclusion: Anyway, count me as +1 on the proposal. It would improve the long-term stability of Haskell code. How is adding more ways to break something "improving the long-term stability"? You seem determined to misunderstand every message in this thread. What I said was that the change from bar-1.0 to bar-1.0.1 breaks the example code *with the current behaviour*. The proposal removes this breakage. Anything that keeps the old code compiling and working with new libraries improves its long-term stability in my book. Note that the bar-1.0.1 upgrade wasn't even a major version change. This is correct according to the PVP: Otherwise, if only new bindings, types, classes, non-orphan instances or modules (but see below) were added to the interface, then A.B may remain the same but the new C must be greater than the old C. but it still breaks the example module. Mind you, while the current proposal only increases the chances that old Haskell code continues to work with new libraries. If my module had defined a function foo itself instead of importing it, the upgrade would still break it. An extended version of the proposal might state that implicitly imported members get shadowed by local definitions as well, but this might be harder to implement. Besides, even this proposal wouldn't protect the importer from new instance imports from clashing with the local ones. There's no shadowing solution in this case. To summarize, the proposal is not providing any hard guarantees, and it's weakening an existing guarantee (see above). I'm still in favour, because it increases the stability of the legacy Haskell codebase. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
On Tue, Oct 21, 2014 at 4:55 PM, Mario Blažević wrote: > On 14-10-21 07:14 AM, Erik Hesselink wrote: >> >> On Mon, Oct 20, 2014 at 11:57 PM, Mario Blažević >> wrote: >>> No, what I find much worse is a cabal update causing an error in >>> a >>> module that was correct before the update. Consider >>> module Main where import Foo (foo) import Bar main = foo >>> >>> >>> Now suppose Bar came from the package bar-1.0, and the new >>> version >>> bar-1.0.1 decides to export foo. With the current behaviour, this change >>> would break my module. With Malcolm's proposal the old code would >>> continue >>> to work. >> >> >> That's a very good point. Given that and the above, I don't understand >> your conclusion: >> >>> Anyway, count me as +1 on the proposal. It would improve the >>> long-term stability of Haskell code. >> >> >> How is adding more ways to break something "improving the long-term >> stability"? > > > You seem determined to misunderstand every message in this thread. > What I said was that the change from bar-1.0 to bar-1.0.1 breaks the example > code *with the current behaviour*. The proposal removes this breakage. > Anything that keeps the old code compiling and working with new libraries > improves its long-term stability in my book. > > Note that the bar-1.0.1 upgrade wasn't even a major version change. > This is correct according to the PVP: You're right, I misread your message. I understand now, and you're right that this is currently something that can break your package, although it happens so rarely that people still depend on major version ranges, even though they sometimes don't use explicit or qualified imports. Regards, Erik ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
The current situation could be summed up as requiring some code duplication when explicitly importing (due to the possibility of one or more redundant hides), while encouraging a sort of measure-twice-cut-once mentality. Not suggesting changing the default; I'll have a proposal detailing the exact semantics and possible consequences of using it on the wiki on Thursday, so that more people can weigh in. Erik Hesselink wrote > On Tue, Oct 21, 2014 at 4:55 PM, Mario Blažević < > mblazevic@ > > wrote: >> On 14-10-21 07:14 AM, Erik Hesselink wrote: >>> >>> On Mon, Oct 20, 2014 at 11:57 PM, Mario Blažević < > mblazevic@ > > >>> wrote: >>>> No, what I find much worse is a cabal update causing an error >>>> in >>>> a >>>> module that was correct before the update. Consider >>>> >>>>> module Main where >>>>> >>>>> import Foo (foo) >>>>> import Bar >>>>> >>>>> main = foo >>>> >>>> >>>> Now suppose Bar came from the package bar-1.0, and the new >>>> version >>>> bar-1.0.1 decides to export foo. With the current behaviour, this >>>> change >>>> would break my module. With Malcolm's proposal the old code would >>>> continue >>>> to work. >>> >>> >>> That's a very good point. Given that and the above, I don't understand >>> your conclusion: >>> >>>> Anyway, count me as +1 on the proposal. It would improve the >>>> long-term stability of Haskell code. >>> >>> >>> How is adding more ways to break something "improving the long-term >>> stability"? >> >> >> You seem determined to misunderstand every message in this >> thread. >> What I said was that the change from bar-1.0 to bar-1.0.1 breaks the >> example >> code *with the current behaviour*. The proposal removes this breakage. >> Anything that keeps the old code compiling and working with new libraries >> improves its long-term stability in my book. >> >> Note that the bar-1.0.1 upgrade wasn't even a major version >> change. >> This is correct according to the PVP: > > You're right, I misread your message. I understand now, and you're > right that this is currently something that can break your package, > although it happens so rarely that people still depend on major > version ranges, even though they sometimes don't use explicit or > qualified imports. > > Regards, > > Erik > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@ > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users -- View this message in context: http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758451.html Sent from the Haskell - Glasgow-haskell-users mailing list archive at Nabble.com. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
It's occurred to me that a much simpler description of the proposed change would be automatically lifting *uses* of the explicitly imported variable to a qualified use, /if/ there was only one explicit import of the identifier. For instance, with the following import: import Data.Text.Lazy.IO (putStrLn) import Prelude import qualified Data.List as L import qualified MyModule as L (isInfixOf) automatically change any unqualified (and un-shadowed) use of putStrLn to Data.Text.Lazy.IO.putStrLn, and any use of L.infixOf to MyModule.isInfixOf. The latter should be easier to implement covering a number of corner cases: * you can still refer to Prelude.putStrLn or Data.List.isInfixOf by prepending the path, which the naive auto-hiding transformation would prevent. * possibly easier to have the pragma available to use in GHCi, since you don't need to retroactively hide identifiers from previously imported modules when a new explicit import is made. * works better with imports like "import Data.Either (Either(..)); import MyModule (Left)", which would otherwise require translating the Data.Either import to something like "import Data.Either (Either(..)) hiding (Left)" which isn't currently possible or "import Data.Either (Either(Right))" which can't be done without knowing which modules export which identifiers. The only remaining corner case is if you shadow the name of a module like: import Data.Text.Lazy.IO (putStrLn) import Prelude as Data.Text.Lazy.IO An unqualified user of putStrLn /should/ refer to the text version, but if anything translating it to Data.Text.Lazy.IO.putStrLn makes it more ambiguous. I assume GHC can disambiguate even if the user can't, or if you didn't want to cover that case the existing ambiguous identifier occurrence error could still fire. Really just depends where in the pipeline the change is implemented. I suppose I'll describe both possible implementations. Functionally they're the same, but maybe this one is simpler. -- View this message in context: http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758463.html Sent from the Haskell - Glasgow-haskell-users mailing list archive at Nabble.com. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
signature.asc Description: Message signed with OpenPGP using GPGMail ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
Proposal is up for your viewing pleasure: http://www.haskell.org/haskellwiki/PermissiveImportsProposal -- View this message in context: http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758553.html Sent from the Haskell - Glasgow-haskell-users mailing list archive at Nabble.com. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Hiding import behaviour
Thanks for writing this up so clearly. I'm +1 on the proposal as written. I think the (smallish) drawbacks are mitigated by the fact that the whole feature is opt-in. Implementation should be relatively straightforward. Thanks, Richard On Oct 23, 2014, at 2:22 PM, htebalaka wrote: > Proposal is up for your viewing pleasure: > http://www.haskell.org/haskellwiki/PermissiveImportsProposal > > > > -- > View this message in context: > http://haskell.1045720.n5.nabble.com/Hiding-import-behaviour-tp5758155p5758553.html > Sent from the Haskell - Glasgow-haskell-users mailing list archive at > Nabble.com. > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users