Haskell Modules Guide — Module Declarations, Exports, and Import Control
In this tutorial, you will learn about Haskell Modules Guide. We cover key concepts, practical examples, and best practices to help you master this topic.
Haskell modules group related definitions with explicit export lists controlling visibility, import statements with qualified and hiding modifiers, and hierarchical naming (Data.List, Data.Map) for namespace management in large projects.
Module Declaration
-- File: src/Geometry/Shapes.hs
module Geometry.Shapes
( Circle(..)
, Rectangle(..)
, area
, circumference
) where
data Circle = Circle { radius :: Double }
data Rectangle = Rectangle { width :: Double, height :: Double }
area :: Circle -> Double
area (Circle r) = pi * r ^ 2
areaRect :: Rectangle -> Double -- NOT exported
areaRect (Rectangle w h) = w * h
circumference :: Circle -> Double
circumference (Circle r) = 2 * pi * r
Importing Modules
-- Full import
import Data.List
import Data.Maybe
-- Qualified import
import qualified Data.Map as Map
import qualified Data.Set as Set
-- Selective import
import Data.List (sort, nub, intercalate)
-- Import everything except
import Data.List hiding (sort)
-- Re-export
module MyModule
( module Data.List
, myFunction
) where
import Data.List
Submodules
-- File: src/Geometry/Circle.hs
module Geometry.Circle where
area :: Double -> Double -> Double
area r = pi * r ^ 2
-- File: src/Geometry.hs
module Geometry
( module Geometry.Circle
, module Geometry.Rectangle
) where
import Geometry.Circle
import Geometry.Rectangle
Common Mistakes
1. Not using export lists
Without an export list, everything is exported. Always specify exports for library modules to hide internals.
2. Circular imports
Module A imports B, B imports A. This creates a compile error. Refactor shared code into a third module.
3. Name clashes
Two imported modules exporting the same name. Use qualified imports or import hiding to resolve.
Practice Questions
1. How do you export only specific functions?
List them after the module declaration: module MyMod (func1, func2) where.
2. What does import qualified do?
Imports require module prefix: qualified Data.Map as Map means Map.lookup, not lookup.
3. How do you avoid name clashes? Use qualified imports, hiding, or import only specific names from each module.
FAQ
{{< faq question="What is the default export behavior?" >}} If no export list is given, everything defined in the module is exported. Add an export list to control visibility.
{{< /faq >}}
{{< faq question="Can I re-export from another module?" >}}
Yes, list module OtherModule in the export list. This is common for convenience modules that bundle related functionality.
{{< /faq >}}
{{< faq question="What is the module naming convention?" >}} Haskell modules use hierarchical dot notation matching directory structure: Data.Map is in Data/Map.hs. {{< /faq >}}
What's Next
Now learn about lazy evaluation in Haskell.
| Topic | Description | Link |
|---|---|---|
| Lazy Evaluation | Laziness and thunks | {{< ref "17-lazy-evaluation" >}} |
| Error Handling | Exception Handling | {{< ref "18-error-handling" >}} |
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro