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 theunfoldr
function defined there, but we would like to define our ownintercalate
function in the current module. An import ofData.List
without import list would also import theintercalate
function defined inData.List
, along with a long list of other functions. When we try to callintercalate
in the current module now, the compiler has no idea which of the two functions we want to call, our own or the one fromData.List
. By specifying that we want to import onlyunfoldr
fromData.List
, the name clash is eliminated because only our own definition ofintercalate
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).