Suggestion: Improved handling of overlapping imports

Mathias Stearn redbeard0531 at gmail.com
Wed Jan 7 04:39:14 EST 2009


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


More information about the Haskell-prime mailing list