Skip to content

Instantly share code, notes, and snippets.

@graninas
Last active April 25, 2024 20:49
Show Gist options
  • Save graninas/1b7961ccaedf7b5cb92417a1599fdc99 to your computer and use it in GitHub Desktop.
Save graninas/1b7961ccaedf7b5cb92417a1599fdc99 to your computer and use it in GitHub Desktop.
Haskell Approaches Comparison Table

An Opinionated Comparison of Software Design Approaches in Haskell

Raw IO Free Monads; Church Encoded Free Monads Final Tagless / mtl Effect Systems ReaderT Service Handle
Core Principle Bare IO monad, imperative code Interpretable, instrospectable, custom pure monads Effects are explicit in BL; a list of constraints Effects are explicit in BL; either a list of constraints, or a list of types Interface to subsystems is described as a control structure and placed to ReaderT environment A Handle structure as an interface to subsystems
- Interfaces None ADTs Type classes; Type classes + type families Different; ADTs; type classes; type families Monadic methods placed into ReaderT env (usually IO methods, but not necessary) Monadic methods placed into a structure (usually IO methods, but not necessary)
- Business Logic Impure monadic Pure monadic Impure monadic; effects are constraints Depends; pure or impure monadic BL in a custom monadic stack with ReaderT Any kind of BL; service handle can be passed either as a parameter or as a ReaderT env
- Implementation Mixed with BL Interpreters Type class instances Different; interpreters; type class instances; type family instances Implementation is filling the control structure Implementation is filling the Handle structure
Separation of Concerns None 5/5 3/5 Depends; 3-5/5 3/5 3/5
Layering - Good, essential, unavoidable Weak; Implementation details tend to leak Depends; 3-5/5; Implementation details tend to leak; Lists of effects prevent dividing a BL into own layers 3/5 3/5
Mechanisms Simplicity 3/5 5/5 1-4/5 1/5 5/5 5/5
Complexity Reduction 1/5 5/5 3/5 2/5 3/5 3/5
Robustness 2/5; No restrictions on effects 5/5 4-5/5; Sometimes IO is allowed 5/5 3/5; No restriction on effects 3/5; No restriction on effects
Maintainability 1/5 5/5 3/5 2/5 3/5; Details are in the BL 3/5; Details are in the BL
Testability 1/5 5/5 2/5 Depends; 3-5/5 Depends; 3-4/5 Depends; 3-4/5
Extensibility 3/5 4/5 4/5 3/5 3/5
- Effects 5/5 2/5 5/5 3/5 3/5 3/5
- Domain Features 4/5 3/5 3/5 5/5 5/5
Rare design cases Will be a mess Approachable, relatively simple Hard, mind blowing, complicated Hard, mind blowing, sometimes extremely complicated 2-3/5; Approachable but often complicated 2-3/5; Approachable but often complicated
Expressiveness Not limited; not convenient Very expressive; Different semantics and syntax is possible; Very limited syntax; limited semantics Very limited syntax; limited semantics 4/5; Limited syntax; limited semantics 4/5; Limited syntax; limited semantics
Boilerplate 3/5 3/5 3/5 3/5 3/5
- Interfaces None 3/5 5/5 Depends; 3-5/5 3/5 3/5
- Business Logic 1/5 5/5 2/5 2/5 4/5 2/5
- Implementation 1/5 4/5 4/5 3/5 4/5 4/5
Error Handling When you're lucky Simple; Error domains Complicated Depends; usually complicated Approachable Approachable
Problems & Limitations Bare IO; Lazy IO; Bad testability; Bad separation of concerns; Bad in general FM: O(n^2) monadic binding; No exceptions in BL All layers are mixed; IO is not separated; No real separation of concerns; Bad testability; Very complicated error handling; Implementation details tend to leak into BL; On rare special cases, design becomes very hard; Too many special hacks for incorporating of some external libraries Explicit type lists of effects are really hard to maintain; A lot of difficult high-level concepts involved; Rigidness and inconvenience to use; Overall overengineering; Often a bad testability; Very complicated error handling; Implementation details tend to leak into BL; On rare special cases, design becomes very hard; Too many special hacks for incorporating of some external libraries All the layers are mixed (usually); Effects are not limited; Too hard to hide implementation details; Hard to maintain; Rare design cases can be hard to implement; All the layers are mixed (usually); Too hard to hide implementation details; Hard to maintain; Rare design cases can be hard to implement;
Performance 4~5/5 FM: 2/5; CEFM: 5/5 5/5 Depends; 4-5/5 5/5 5/5
Docs & Showcases
Market Share
Overall Bad approach; suitable for small apps; Not suitable for big real-world apps Very powerful. Best testability. Best expressiveness. Best complexity reduction. Best layering. Introspection is very useful. An approach for lazy developer. Doesn't satisfy the requirements. Suitable when there is no time for design. Not really suitable for big codebases. An approach for those who wants to control everything in the BL. Lists of effects prevent dividing a BL into own layers. Relatively simple. Can be used for small and middle apps. Code tends to become polluted by implementation details. No explicit guarantees Relatively simple.Can be used for small and middle apps.Code tends to become polluted by implementation details.No explicit guarantees
@alaendle
Copy link

alaendle commented Feb 1, 2024

@graninas, just wanted to let you know that I just pre-ordered the second edition of your book to continue my journey to sound haskell application architecture 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment