Modules
Prerequisites: Algebraic data types
A module is one .hs file with a name. Modules group related code,
control what's visible to other code, and make up libraries.
Importing
import Data.List (sort, nub)
import qualified Data.Map as Map
import Data.Char hiding (isSpace)
import qualified Data.Set as S
main :: IO ()
main = do
print (sort (nub [3, 1, 3, 2]))
print (Map.toList (Map.fromList [(1, "one"), (2, "two")]))
print (toUpper 'q')
print (S.member 2 (S.fromList [1, 2, 3]))
[1,2,3]
[(1,"one"),(2,"two")]
'Q'
True
| Form | Effect |
|---|---|
import M |
Everything M exports, unqualified |
import M (a, b) |
Only a and b |
import M hiding (c) |
Everything except c |
import qualified M as N |
Everything, but only as N.name |
Modules like Data.Map reuse names from the Prelude (filter, map,
lookup), so they're almost always imported qualified.
Writing a module
A module file starts with module Name (exports) where, and its path
must match its name: Geometry.Shapes lives in Geometry/Shapes.hs.
-- illustrative: file Geometry/Shapes.hs
module Geometry.Shapes
( Shape (..)
, area
, Point
, mkPoint
) where
data Shape = Circle Double | Square Double
deriving (Show)
data Point = Point Double Double
deriving (Show)
mkPoint :: Double -> Double -> Maybe Point
mkPoint x y
| x >= 0 && y >= 0 = Just (Point x y)
| otherwise = Nothing
area :: Shape -> Double
area (Circle r) = pi * r * r
area (Square s) = s * s
helper :: Int
helper = 42 -- not exported: private to this module
-- illustrative: file Main.hs, next to the Geometry folder
module Main (main) where
import Geometry.Shapes
main :: IO ()
main = do
print (map area [Circle 1, Square 2])
print (mkPoint 1 2)
[3.141592653589793,4.0]
Just (Point 1.0 2.0)
Shape (..)exports the type and its constructors.Pointwithout(..)exports only the type: other modules can't use thePointconstructor, so everyPointmust go throughmkPoint, which validates it. This is the smart constructor pattern — the Haskell way to enforce invariants.- A file without a
moduleline ismodule Main (main) where.
Run the example from the folder containing Main.hs with
runghc Main.hs — GHC finds Geometry/Shapes.hs automatically. In a
cabal project, you list modules in the .cabal file instead (see the
last lesson of this level).
Packages
Modules come from packages. base (the Prelude, Data.List,
Data.Char, Control.Monad, ...) is always available. Packages such as
containers (Data.Map, Data.Set), text, bytestring, mtl, and
stm ship with GHC; everything else comes from Hackage, Haskell's
package repository, via cabal.