When I develop Haskell packages, I usually use the following structure of the project directory.
Top-level project layout
For a single-package project ALPHA it should be
ALPHA/
├── stack.yaml/cabal.project
├── ALPHA.cabal
└── ...other package files...see below...
For a project containing multiple packages (say, BETA and GAMMA)
ALPHA/
├── stack.yaml/cabal.project
├── BETA/
│ ├── BETA.cabal
│ └── ...other BETA package files...
└── GAMMA/
├── GAMMA.cabal
└── ...other GAMMA package files...
Package layout
Let’s take a look into the GAMMA package. First, the cabal file. Nowadays, Cabal format is good enough, so we don’t need hpack anymore.
GAMMA/
├── GAMMA.cabal
└── ...
Each component goes into a separate folder
GAMMA/
├── GAMMA.cabal
├── lib/ -- library(ies)
├── exe/ -- executable(s)
├── test/ -- test(s)
└── bench/ -- benchmark(s)
(Michael Snoyman likes src for the library and app for the executable. I don’t get it.)
If there is only one component of each type, its files are put into its directory.
If I need to have multiple components of some type, I create one more folder level.
GAMMA/
├── GAMMA.cabal
│ ╭───────────────────────────────────────────────────────────╮
│ │... │
│ │ │
│ │library -- public library │
│ │ hs-source-dirs: lib/GAMMA -- same name as the package │
│ │ │
│ │library DELTA -- internal library │
│ │ hs-source-dirs: lib/DELTA │
│ │ │
│ │... │
│ ╰───────────────────────────────────────────────────────────╯
└── lib/
├── GAMMA/
│ └── GAMMA.hs -- usually the main module and the package have
│ -- the same name
└── DELTA/
└── DELTA.hs
Same for executables, test-suites and benchmarks
GAMMA/
├── GAMMA.cabal
│ ╭───────────────────────────────╮
│ │... │
│ │ │
│ │executable EPSILON │
│ │ hs-source-dirs: exe/EPSILON │
│ │ main-is: Main.hs │
│ │ │
│ │executable ZETA │
│ │ hs-source-dirs: lib/ZETA │
│ │ main-is: Main.hs │
│ │ │
│ │... │
│ ╰───────────────────────────────╯
└── exe/
├── GAMMA/
│ └── Main.hs
└── DELTA/
└── Main.hs
Module naming
No ancient Control/Data/Network namespace prefixes.
Main module of an executable/test-suite/benchmark is always Main.hs (sometimes Main.lhs).
All other modules are in package namespace (GAMMA.Text.Parser) or in project-package one (ALPHA.GAMMA.Text.Parser).
Comments?
https://t.me/haskell_and_curry/2