Suggestion: Improved handling of overlapping imports

I've noticed an annoying (anti)pattern when using modules that collide with other modules (esp with the prelude). I find this is most common with modules conflicting with Data.List or System.IO. I'm fairly new to Haskell (did a little last January with XMonad and Just now getting back into it) so maybe there is a better way to handle this. Example: import Data.Foldable (minimum, minimumBy, maximum, maximumBy) import Data.List hiding (minimum, minimumBy, maximum, maximumBy) import Prelude hiding (minimum, maximum) import System.IO.UTF8 (putStrLn, hPutStrLn) import System.IO hiding (putStrLn, hPutStrLn) import Prelude hiding (putStrLn) As you can see this can be quite annoying and is a disincentive to use improved or more general tools. Especially worrisome is that it is not obvious what you must hide from the Prelude. If you try to hide hPutStrLn or minimumBy you get an error. I found this led to a lot of trial and error (read: guess and check). I have a few ideas on how to solve this.The first two are using current syntax and simply doing what the programmer really meant. The third one is adding new syntax to allow a programmer to specify what they mean. All three should be able to work either together or separately. 1) Transitive Hiding If you hide something when importing a module it automatically hides identical imports. I cant think of a situation where this isn't what the user would want. This also seems easy to implement because the compiler already must know which functions are identical when checking for ambiguities. 2) Explicit Import Lists Take Precedence Any ambiguity should be resolved in favor of the module that has the name explicitly in its import list. An additional advantage here is that it offers some protection against a program breaking if a function is added to a module. This can be considered an extension of the current ImportShadowing (http://hackage.haskell.org/trac/haskell-prime/wiki/ImportShadowing) proposal if the current module is thought of as imported with everything explicit. 3) Import A Shadowing B This actually adds a new import style which I think is the best solution: import System.IO.UTF8 shadowing System.IO import Data.Foldable shadowing Data.List In each case all functions in A would shadow any function in B. I think this should behave like Transitive Hide where the identical Prelude functions would also be shadowed. A major advantage here is that it allows drop-in replacements for the standard libs to be easily used. A few things I could go either way on with this: 3.1) if minimum was explicitly imported from Data.List do we use it, Foldable.minimum, or do we error out? 3.2) if a module reexports Data.Foldable should it also reexport the shadowing? I could see this being useful on a big project where you import a module that reexports several modules shadowing the Prelude to create a specialized standard lib. 3.3) should there be a shadowing all? I may take a peek at GHC this weekend to see how easy it would be to add any of these as optional extensions. ~Mathias Stearn

Mathias | I've noticed an annoying (anti)pattern when using modules that collide | with other modules (esp with the prelude). I find this is most common | with modules conflicting with Data.List or System.IO. I'm fairly new | to Haskell (did a little last January with XMonad and Just now getting | back into it) so maybe there is a better way to handle this. | | Example: | import Data.Foldable (minimum, minimumBy, maximum, maximumBy) | import Data.List hiding (minimum, minimumBy, maximum, maximumBy) | import Prelude hiding (minimum, maximum) | | import System.IO.UTF8 (putStrLn, hPutStrLn) | import System.IO hiding (putStrLn, hPutStrLn) | import Prelude hiding (putStrLn) Yes, I've seen this too. | 1) Transitive Hiding | If you hide something when importing a module it automatically hides | identical imports. I don't like this because a 'hiding' clause on one import affects other imports. Yuk. | 2) Explicit Import Lists Take Precedence | Any ambiguity should be resolved in favor of the module that has the | name explicitly in its import list. ...This can be considered an extension of | the current ImportShadowing | (http://hackage.haskell.org/trac/haskell-prime/wiki/ImportShadowing) | proposal if the current module is thought of as imported with | everything explicit. I like this. It's in the same spirit as the ImportShadowing proposal, so if that proposal is accepted, then this one makes sense too. (If not, then think again.) Why don't you modify the ticket to add your proposal to it. | 3) Import A Shadowing B | This actually adds a new import style which I think is the best solution: | | import System.IO.UTF8 shadowing System.IO | import Data.Foldable shadowing Data.List I'm not keen on this. Not only is it new syntax, but it leads to the same repeats as you objected to earlier: import System.IO.UTF8 shadowing Prelude import System.IO shadowing Prelude import Prelude So for me (2) is a clear winner. Simon
participants (2)
-
Mathias Stearn
-
Simon Peyton-Jones