Skip to content

Import Lists

Just as an export list as part of a module header specifies the list of definitions exported by a module, we can use an import list to specify the list of definitions to be imported from a module. For example,

import Data.List (unfoldr, intercalate)

imports only the two functions unfoldr and intercalate from the Data.List module.

When importing data types, we can choose to import only the type or the type and its data constructors. Thus, we can choose to treat the type as an opaque type or as a transparent type. Again, we choose this by importing the type using

import Control.Monad.State (StateT)

for an opaque import or using

import Control.Monad.State (StateT(..))

for a transparent import. Of course, we have this choice only if the module from which we're trying to import the type does in fact export it transparently. If the exported type is opaque, we can only import it as an opaque type.

You may wonder why we would import only some definitions from a module and not others. There are two primary reasons:

  • Avoiding name clashes: When importing some or all functions from a module, these functions can be called as any other function defined in the current module. This can lead to name clashes. For example, we may import Data.List to gain access to the unfoldr function defined there, but we would like to define our own intercalate function in the current module. An import of Data.List without import list would also import the intercalate function defined in Data.List, along with a long list of other functions. When we try to call intercalate in the current module now, the compiler has no idea which of the two functions we want to call, our own or the one from Data.List. By specifying that we want to import only unfoldr from Data.List, the name clash is eliminated because only our own definition of intercalate is visible in the current module.
  • Documentation: For most standard library functions, the experienced Haskell programmer knows which modules define them. Even if they don't know, they can always consult Hoogle to find out where each function is defined, and what it does. This changes when we break our own project into multiple modules, and the modules in our project import each other. When using blanket imports (imports without explicit import lists) of multiple modules that are part of our own project, the reader of our code cannot tell from which module a function we're calling was imported. By providing explicit import lists, we document which function we're importing from which module. It has become common practice among Haskell programmers to always use explicit import lists or qualified imports (discussed next).