Extending the functional core

(Pre-req: Functional core, imperative shell architecture)

  • The functional core is more testable and more composable than the imperative shell or effectful code
  • Sometimes you can easily extend the functional core by lifting out side-effects to calling code
  • Sometimes, the side-effects are entangled inside business logic
  • This can be dealt with in different ways depending on the type of the side-effects

Consider the following categories of effects:

  • Effects that can be delayed
  • Effects that depend on each other
  • Effects where the result is needed at once

Function que to add lambda to queue, like que (fun () -> <effectful thing>), then run the queue in the imperative shell, like IO.run_queue

Function seq for a sequence of lambdas where each is run only if previous returns true. Harder to read than “normal” program flow.

When the result is needed at once, consider either yield/generator system (using OCaml’s new effect system), or an IO module that is mocked during unit testing.

In functional programming, and Haskell, you also have strategies like Free Monad, or tagless-final, to life out side-effects. Strategies that do increase the complexity of the code, and also don’t differ between the different categories of effects.

Did an example implementation in PHP here: que.md · GitHub

But maybe I’ll ask the Haskell guys instead. :slight_smile:

I don’t see any question in your posts. What are you meaning to ask, can you clarify?


Well, shit. I wanted to ask about strategies to extend the functional core. I think the Free Monad is the closest bet in OCaml…?