A module is a separately organized unit of code with a defined responsibility and boundary. It concentrates related functionality while controlling which types and operations external code can use. section 3.2.4 section 4.1.1
Modules protect unstable internals through opaque types and explicit exports. Exposing only a type and smart constructors prevents clients from depending on concrete constructors, so internal representation can change without breaking dependent code. section 3.2.4
Good module boundaries make responsibilities and dependencies visible:
- Keep common types in a shared module usable across domain, language, implementation, and asset layers. section 4.1.1
- Keep implementation modules independent of concrete assets such as vendor-specific devices; represent those details as configuration in an asset layer. section 4.1.1
- Use top-level modules to reexport stable subsystem interfaces while hiding their internal module layout. section 3.2.4
An opaque value module
A value module can export `Value`, `boolValue`, `stringValue`, and `intValue` while withholding `BoolValue`, `IntValue`, `FloatValue`, and `StringValue`. Clients construct valid values through the smart constructors instead of pattern matching on representation-specific constructors. section 3.2.4
Listing 3.8 Structure of Andromeda Control Software
-- file src\Andromeda.hs: module Andromeda ( module Andromeda.Simulator #1 , module Andromeda.Common ) where import Andromeda.Simulator #2 import Andromeda.Common -- file src\Andromeda\Simulator.hs: module Andromeda.Simulator #3 ( module X ) where import Andromeda.Simulator.SimulationModel as X #4 import Andromeda.Simulator.Simulation as X import Andromeda.Simulator.Actions as X
Browse a reexporting module structure that presents the simulator and common functionality through a top-level interface. section 3.2.4


































