Skip to content

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).