6 ms·
On hacker news someone told me a another name for this pattern: "Functional core, imperative shell". edit: I see other people have mentioned it. One of the big
by corethree 3y ago
On hacker news someone told me a another name for this pattern: "Functional core, imperative shell". edit: I see other people have mentioned it.
One of the biggest issues with this pattern is if there's a ton of IO that's necessary for the application. If that's the case you'll see that the "bread" of the sandwich's is gigantic while the "meat" is very small and tiny.
This is the case with most web applications. The bread is sort of the main problem though but with this pattern we don't actually attempt to solve that problem, instead we just try to segregate the main problem away from pure code that intrinsically doesn't have that problem anyway. Don't get me wrong. The segregation is correct, but the problem of IO and mutating state is still unsolved.
- jfoutz 3y agoIt’s unsolved. The bread part is poker, and the meat part is chess. Yes, there is a ton of io, but the meat can pick the strategy. Try this call no more than 3 times in 60ms, and get back to me. It’s complicated and frustrating and not always worth it, but even with lots of io, the logic, the strategy, can live in the pure compositional parts. Your mileage may vary, but it’s often worth a little thought at least.
- corethree 3y agoOf course. Nowadays though it's mostly metadata programming. Your haskell code is writing code for your database query. So you end up using functional code to do tons of IO and the data it sends to IO is just more code.
- lmm 3y agoThe IO doesn't usually involve business logic, almost by definition. A web service can usually make a pretty good sandwich if it's actually doing anything - you do a thin state fetch, a thick business computation on that state, and then a thin write / return to the user. There are definitely cases where your business logic and your I/O are more tightly interleaved so that you can't really separate them the same way, and the post mentions that and links to https://blog.ploeh.dk/2017/07/10/pure-interactions/ https://blog.ploeh.dk/2017/07/10/pure-interactions/ as a deeper guide for those cases.
- corethree 3y agoIn web, IO is heavily intertwined with business logic and mutation. In fact most of the computation is done via the database. Database code is mutation heavy and offloaded as IO away from the web application. The web application is in fact just a thin routing layer. It is not a one off case.
- lmm 3y ago> In web, IO is heavily intertwined with business logic and mutation. In fact most of the computation is done via the database. Database code is mutation heavy and offloaded as IO away from the web application. The web application is in fact just a thin routing layer. That's one way of writing a web service. It's not the only or even "normal" way - IME it's much more common to have the database act as a dumb CRUD key/value store, and put logic in the application layer (indeed many web services use a pure key/value store rather than a "database" as such). You're right that if your logic is in the database, and it's an ACID-style "mutate the current state of the world" database then you can't really use pure functional techiques. The only solution to that is to not do that.
- corethree 3y ago>That's one way of writing a web service. It's not the only or even "normal" way - IME it's much more common to have the database act as a dumb CRUD key/value store, and put logic in the application layer (indeed many web services use a pure key/value store rather than a "database" as such). Wrong. The normal way is SQL. Web applications are suppose to be written in ways as nonblocking as possible. As much logic that can be pushed to the database as possible. That is the way to go. This reduces round trip time by a huge amount. The pure key/value store is non-standard, but it is a way to do it. Not the traditional way and not the majority way either. Many of the major web application frameworks assume SQL as the underlying database not mongo or some other key value db. >You're right that if your logic is in the database, and it's an ACID-style "mutate the current state of the world" database then you can't really use pure functional techniques. The only solution to that is to not do that. Not only am I right. It's the main way things are done on the web. The functional layer is largely just code generation: Pure Functions with http requests as input and SQL code as output. This is the core model.
- mrkeen 3y ago> One of the biggest issues with this pattern is if there's a ton of IO that's necessary for the application. Yes, that's why patterns like this are necessary. Do you stop doing dependency inversion when you have too many dependencies?
- corethree 3y agoYou're not getting it. When there's so much IO, which is what happens in a lot of web applications, most of your code isn't going to be pure anyway. Even your haskell code under do-notation looks very procedural because there's just so much IO. So you're basically back to programming regular code. It doesn't solve the core problem. The pattern itself is good and is not a problem and I believe the pattern that should be followed.... but in the end practically speaking for the web it doesn't do too much to remove the main issue.