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 |
-
-
Save graninas/1b7961ccaedf7b5cb92417a1599fdc99 to your computer and use it in GitHub Desktop.
@alaendle, sure, you're welcome!
Just to note: some effect systems have Free monads under the hood. The very fact of this gives you the interpretation possibility. All my Free monadic solutions are interpretable in the same sense (yes, the natural transformation). The difference is how we track the effects. The effect systems ask you to compose effects as type level list of types, but I don't like this very much. For me it goes out of control quickly. My approach is to nest the Free monadic languages one into another.
I find your experience with ReaderT and mtl very interesting.
And please don't forget that these are questions and feedback from a beginner
Sure. I think many of my materials are pretty much advanced though. Don't hesitate to ask questions :)
@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 😄
"But the industry is not interested in advanced Math concepts, it's not interested in cool smart things, it doesn't value curiosity as haskellers do. " - so, we programmers, shoudnt give a f..ck about industry.
@graninas, first 👍 and ❤️ .
Thank you so much for theses detailed descriptions.
So to really tell you what I think I first have to gain some more experience - especially with the free monad stuff. As a Haskell beginner, I only have experimented final tagless, readerT, raw IO and now effect systems.
Maybe its because I'm having a OOP background - but the effect systems stuffs seemed very compelling to me (at least at a first glance); I think because of its principal simplicity - when you consider the interpreters as a natural transformation (step) from your DSL to the actual program. I also think ReaderT just reminded me to simple dependency injection and therefore just felt wrong (because it couldn't really hide the "lower aspects" - and needs lot of boilerplate code). Also the limited (read: hard) composability of mtl stuff doesn't make it as a concept useful to me.
So maybe I just have to try to realize/refactor my project using Free Monads - to really get a feeling for that approach. But first I have to read trough the referenced posts and watch some videos, so that I become aware of what I am getting myself into.
I will post an update once I made some progress (in whatever direction). And please don't forget that these are questions and feedback from a beginner - so please perceive my statements against my limited Haskell/FP experience.
And once again many thanks for your effort to answer my questions in such detail.