|
|
|
|
|
by Twisol
1987 days ago
|
|
In Haskell, you often build pure transformations, and then lift them into an effectful context. If I have a function `String -> [String]`, say to parse a line of CSV into its elements, I can lift that to `IO String -> IO [String]` using the IO monad's `fmap`. And then I can compose it with something hypothetical like `readLine :: File -> IO String`, which actually reads the line. The core logic of a program often doesn't need to care deeply about state or system resources. Pure functional programming is about writing as much as you can in this "functional core", and then lifting the assembled pieces of pipeline into the "imperative shell" (such as the IO monad). |
|
In our case, almost all core code depends on various parameters, which come from the database.
For example, GB recently left the EU so everything involving GB is now processed under different rules, except old stuff which has to be processed under the old rules. Thus being part of EU or not is a date-dependent database query (it already was, not the first time a country's EU status has changed).
So if I get your explanation correctly, I'd code the core logic as if these parameters were pure, side-effect free, which would make the core logic side-effect free. In the case above, I'd pass a function which maps a (pure) date and string into a (pure) bool, to test for EU membership.
I'd then turn that whole thing dirty via the IO thingy, passing "IO parameters" and receiving "IO results", so I can pass it my EU test function which does a database query.
edit: And I presume my "dirty" database-connecting function can also mutate things, so it can do caching. Don't want to hit that database too often.