Qualified Imports
Import lists help to avoid name clashes in many situations but not always. There
are numerous widely used packages whose modules provide functions with the same
names, and with good reason. For example, there exists a map
function for
lists (defined in Data.List
and also included in the Prelude
), and the
Data.Array
module of the array
package also provides a map
function, one
that operates on arrays. Given that these two functions do the same thing—only
one does it for lists, and the other for arrays—it is a good thing that they
have the same name. The user of the Data.Array
module recognizes the familiar
function name and can immediately guess what the function does. However, it is
not uncommon to implement modules that need to manipulate both arrays and lists,
and thus may need access to both the map
function for lists and the map
function for arrays. After importing Data.Array
even with an explicit import
list
import Data.Array (map)
our module can no longer call just map
anywhere, because there are now two
map
functions in scope, and the compiler cannot tell which one we want to
call. We can disambiguate the function calls by using qualified function names.
Every function f
imported from some module M
can be called using its fully
qualified name M.f
. Thus, we could distinguish between the map
function
(automatically) imported from the Prelude
and the map
function imported from
Data.Array
by calling either Prelude.map
or Data.Array.map
.
We can avoid having to use one of these qualifications by using qualified imports. If we use the import statement
import qualified Data.Array
then every function imported from Data.Array
can only be called using its
qualified name. Thus, calling map
once again refers to the map
function from
the Prelude
. To call the map
function from Data.Array
, we must use the
fully qualified name Data.Array.map
.
When using qualified imports, it is common to omit an explicit import list. Since the definitions from the module are imported using only their qualified names, importing everything from such a module cannot cause any name clashes, and calling any function from such a module cannot leave the reader of our code guessing which module defines the function we're calling because we must call the function using its fully qualified name. However, it is allowed to combine qualified imports and import lists, as in
import qualified Data.Array (map)
This says that we want to import only the map
function from Data.Array
and
that the import is qualified, that is, we can call this function in the current
module only using its fully qualified name Data.Array.map
.
It is also common to combine both qualified and unqualified imports of the same module. For example, many Haskell programmers find qualified names in type signatures distasteful but are perfectly fine with using qualified names in function definitions. So they end up importing types unqualified, and functions qualified. For example,
import Data.Array (Array)
import qualified Data.Array
allows us to use the Array
type in type signatures in its unqualified form,
because we imported it using an unqualified import of Data.Array
. All
functions from the Data.Array
module need to be called using their fully
qualified names (e.g., Data.Array.map
).