Good data structures (like zippers) can make some classes of testing needless, as they rule out e.g. out of bounds errors statically.
Provide objective evidence of your programsprogram's heap and time profiles.
Heap profiling, in particular, is the best way to ensure no unnecessary memory use.
QuickCheck + Haskell Code Coverage, to ensure you are testing the things you can't check with types.
GHC +RTS+ RTS is great for seeing if you're spending too much time doing GC.
QuickCheck can also help you identify clean, orthogonal APIs for your modules. If the properties of your code are difficult to state, they're probably too complex. Keep refactoring until you have a clean set of properties that can test your code, that compose well. Then the code is probably well designed too.
Use the type system to enforce abstractions, simplifying interactions.
Enforce key invariants via types
* (e.g. that certain values cannot escape some scope)
* That certain code does no IO, does not touch the disk
Good data structures (like zippers) can make some classes of testing needless, as they rule out e.g. out of bounds errors statically.
Provide objective evidence of your programs heap and time profiles.
Heap profiling, in particular, is the best way to ensure no unnecessary memory use.
QuickCheck + Haskell Code Coverage, to ensure you are testing the things you can't check with types.
GHC +RTS is great for seeing if you're spending too much time doing GC.
QuickCheck can also help you identify clean, orthogonal APIs for your modules. If the properties of your code are difficult to state, they're probably too complex. Keep refactoring until you have a clean set of properties that can test your code, that compose well. Then the code is probably well designed too.
Use the type system to enforce abstractions, simplifying interactions.
Enforce key invariants via types
* (e.g. that certain values cannot escape some scope)
* That certain code does no IO, does not touch the disk
Good data structures (like zippers) can make some classes of testing needless, as they rule out e.g. out of bounds errors statically.
Provide objective evidence of your program's heap and time profiles.
Heap profiling, in particular, is the best way to ensure no unnecessary memory use.
QuickCheck + Haskell Code Coverage, to ensure you are testing the things you can't check with types.
GHC + RTS is great for seeing if you're spending too much time doing GC.
QuickCheck can also help you identify clean, orthogonal APIs for your modules. If the properties of your code are difficult to state, they're probably too complex. Keep refactoring until you have a clean set of properties that can test your code, that compose well. Then the code is probably well designed too.