How to organize files in Haskell programs?

haskell.org defines two file and directory layouts that may be helpful, along with some tool guidance.

  • A minimal project layout is based on Hnop.
  • A larger-scale structure for bigger projects.

I know this is a very old question, but as a beginner struggling with this I still have not found a satisfying answer and there seems to be very little guidence on how to layout a project.

Here is what I have found to be useful.

Essentially project layout is there to give us an idea about where to start when we are developping, so it is closely linked to how we develop programs. For example, in java and the like you do the interface, then implment it. Distinguishing interfaces from classes help you to sort what comes first and what comes after.

The same thing goes for haskell as well in the sense that your development pattern, where you start implementing your idea roughly decides how you layout your project.


Here is a extract from one my small projects:

- README.md
- LICENSE
- docs/
- package.yml
- stack.yml
- Setup.hs
- tests/
  - SomeTypeSpec.hs
- app/
  - Main.hs
- src/
  - Primitive/
    - Definition/
      - SomeType.hs
      - Error.hs
    - Instance/
      - SomeType.hs
  - FunctionDef/
    - Setter.hs
  - Control/
    - SomeType.hs
    - MyProcess.hs

And the way I iterate over this is the following:

  • Write a SomeType.hs under Definition which has some adt.
  • Write related errors about SomeType inside Error.hs
  • Write implementations of Setter.hs by SomeType under Instance
  • Write control functions about SomeType.hs according to application logic under Control
  • Write a small test suite about what the functionality related to SomeType.hs under tests
  • Fix compile errors.
  • Fix compile errors.
  • Fix compile errors.
  • Fix compile errors. . . .
  • Repeat the same process with another primitive

The main constraint is that hierarchical module names must have hierarchical directory layout.

So Data.Map.Fast goes into Data/Map/Fast.hs

After that, decompose your programs and libraries into logical units, in separate modules, and let dependency resolution resolve the modules as needed.