Re-Exports
The final topic we need to touch on is that of re-exports. Let's stick with our example of implementing the Banner system in Haskell. We would probably have a list of modules that implement the different components of the system. Something like
Banner.StudentRecord
Banner.Transcript
Banner.Database
Banner.WebInterface
and probably a whole list of additional modules. Splitting the code base into
separate modules that implement functions to manipulate student records, to
manipulate transcripts, to talk to the database backend, and to talk to a web
frontend allows us to organize our code into self-contained components with a
well-defined interface between them. However, an application working with a
StudentRecord
often also wants to access the student's Transcript
, and
probably retrieves the records to work with from the Banner database. Thus, it
needs functions from Banner.StudentRecord
, Banner.Transcript
, and
Banner.Database
. It needs to import all three modules
import Banner.StudentRecord
import Banner.Transcript
import Banner.Database
This gets tedious quickly. To this end, we would like to create a wrapper module
Banner
that provides all the most commonly used functions of the Banner
system. To this end, the Banner
module imports all the commonly used functions
from the specialized modules and then simply re-exports them by adding them to
its export list, like so:
module Banner
( StudentRecord
, bannerNumber
, name
, address
, transcript
, Transcript
, retrieveRecords
, storeRecords
, processWebQuery
) where
import Banner.StudentRecord
(StudentRecord, bannerNumber, name, address, transcript)
import Banner.Transcript
(Transcript)
import Banner.Database
(retrieveRecords, storeRecords)
import Banner.WebInterface
(processWebQuery)
For most use cases, it will now be enough to simply import Banner
and use the
types and functions exported by Banner
. Banner
probably won't export every
function exported by the more specialized modules. We would then import those
specialized modules only when we need functions they provide that are not
re-exported by Banner
.
As a more concrete example, you may remember that the Haskell Prelude
is the
module automatically imported into every Haskell source code file and which
provides a long list of standard library functions. The Prelude
does not
define any of those functions itself. It consists of a long list of imports from
Data.List
, Data.Maybe
, Data.Either
, etc, etc, etc, and then it re-exports
those imports.
The list of functions imported from Data.List
includes the most commonly used
ones, such as map
and filter
, but it does not include more esoteric ones,
such as unfoldr
. Thus, when we only need map
and filter
, there is no need
to import Data.List
. If we need unfoldr
, we have to import it explicitly
from Data.List
.