Modules and Project Structure
15.1 Modules and Imports
Smart constructors plus hidden data constructors enforce invariants (only valid values can be created).
-- src/Geometry/Shapes.hs
module Geometry.Shapes
( Shape (..) -- export the type and all constructors
, Point -- export the type only (abstract: constructors hidden)
, mkPoint -- smart constructor
, area
) where
data Shape = Circle Double | Square Double deriving Show
data Point = Point Double Double deriving Show
mkPoint :: Double -> Double -> Maybe Point
mkPoint x y
| isNaN x || isNaN y = Nothing
| otherwise = Just (Point x y)
area :: Shape -> Double
area (Circle r) = pi * r * r
area (Square s) = s * s
helper :: Int -- not exported: private to the module
helper = 42import Geometry.Shapes -- everything exported
import Geometry.Shapes (Shape (..), area) -- specific names
import qualified Data.Map.Strict as Map -- qualified: Map.insert, Map.lookup
import Data.Map.Strict (Map) -- import the type unqualified alongside
import Data.List hiding (insert) -- everything except insert
import Prelude hiding (lookup)15.2 A cabal Project
my-project/
├── my-project.cabal
├── cabal.project -- optional: multi-package config
├── app/Main.hs -- executable
├── src/MyLib.hs -- library
├── test/Spec.hs -- test suite
└── bench/Bench.hs -- benchmarkscabal-version: 3.0
name: my-project
version: 0.1.0.0
build-type: Simple
common shared
default-language: GHC2021
ghc-options: -Wall -Wcompat -Wincomplete-uni-patterns -Wredundant-constraints
build-depends: base >=4.17 && <5
library
import: shared
hs-source-dirs: src
exposed-modules: MyLib
build-depends: containers, text
executable my-project
import: shared
hs-source-dirs: app
main-is: Main.hs
build-depends: my-project
test-suite spec
import: shared
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Spec.hs
build-depends: my-project, hspec, QuickCheckcabal build
cabal run my-project -- --some-arg
cabal test
cabal repl # GHCi with the project loaded
cabal update # refresh the Hackage index
cabal freeze # pin versions (cabal.project.freeze)
cabal haddock # generate documentation