Import modules properly
- This page addresses an aspect of Haskell style, which is to some extent a matter of taste. Just pick what you find appropriate for you and ignore the rest.
Haskell has a lot of variants of importing identifiers from other modules. However not all of them are as comfortable as they seem to be at the first glance. We recommend to focus on the following two forms of import:
import qualified Very.Special.Module as VSM import Another.Important.Module (printf, (<|>), )
import Very.Special.Module import Another.Important.Module hiding (open, close, )
Stylistic reason:If you read
In the second case, if new identifiers are added to the imported modules they might clash with names of other modules.
Thus updating imported modules may break your code.
If you import a package A with version a.b.c.d that follows the Package versioning policy
then within versions with the same a.b it is allowed to add identifiers.
This means that if you import the suggested way, you can safely specify
A >= a.b.c && <a.b+1 in your Cabal file.
Otherwise you have to chose the smaller range
A >= a.b.c && <a.b.c+1.
and with a module update removing that identifier, your import fails. That is, an identifier that you never needed but only annoyed you, annoys you again, when it was meant to not bother you any longer! The first variant of import does not suffer from these problems.
Correctness reason: I once found a bug in the StorableVector package by converting anonymous imports to explicit imports.I found out that the function
although functions from this module always have to calcuate with unit "element" not "byte".That is,
A misbehaviour could only be observed for sub-vectors and elements with size greater than 1 byte. The test suite did miss that.
1 Exception from the rule
Since the Prelude is intended to be fixed for the future,it should be safe to use the
Actually if you do not mention Prelude it will be imported anonymously.
2 Clashing of module name abbreviations
In Haskell it is possible to use the same abbreviation for different modules:
import qualified Data.List as List import qualified Data.List.Extra as List
This is discouraged for the same reasons as above:
Stylistic reason:The identifier
The reader of that module has to check these modules in order to find it out.
Compatibility reason:The function
3 Counter-arguments to explicit import lists
The issue of whether to use explicit import lists is not always clear-cut, however. Here are some reasons you might not want to do this:
- Development is slower: almost every change is accompanied by an import list change, especially if you want to keep your code warning-clean.
- When working on a project with multiple developers, explicit import lists can cause spurious conflicts, since two otherwise-unrelated changes to a file may both require changes to the same import list.
For these reasons amongst others, the GHC project decided to drop the use of explicit import lists. We recommend using explicit import lists when importing from other packages, but not when importing modules within the same package.
Qualified use of identifiers does not suffer from the above problems.