Remix.run Logo
taeric 7 hours ago

The problem with this is still that you are sticking with the algebra over the boolean values. And you are going to use + and * in doing so.

Then, you are going to move to discussing the algebra over types and effects. In such a way that you don't actually use + or * to represent the operations.

Quekid5 2 hours ago | parent [-]

I'm not if sure if this is what you're asking for, but to make it very explicit, e.g. Console Output might be modeled as

   data ConsoleOutput =
        PrintLn String
      | PrintWithMode (Mode * String)
      | ...
where | is another spelling of + (which is pretty standard if you look at boolean algebra) and the product is the usual tuple constructor. The is a simple algebraic data type which defines 'an effect' ... it doesn't define the semantics (that's defined by a handler), but it's an 'api' for an effect of some sort.

Obviously, the above definition is a bit contrived, but that's my understanding of why these things are called 'algebraic' effects. It's not that ConsoleOutput and ConsoleInput (however you define that using + or *) are magically 'composable' just because they're both algebraic... for that composition you need extra rules (however you specify that) because effects don't (in general) compose.