Skip to content

Instantly share code, notes, and snippets.

@monadplus
Last active January 13, 2020 21:43
Show Gist options
  • Save monadplus/4a0aaf97b8aa6bbb21df361148c29f12 to your computer and use it in GitHub Desktop.
Save monadplus/4a0aaf97b8aa6bbb21df361148c29f12 to your computer and use it in GitHub Desktop.
Algebraic Effects

Is having an algebraic effect important?

Given a monadic operation

op :: forall a. (M a, ..., M a) -> M a

then it is algebraic if it satisfies the following law:

op (p1, ..., pn) >>= k = op (p1 >>= k, ..., pn >>= k)

In other words, >>= distributes over the operation.

Well, in the absolute simplest case, algebraic operations are operations where the monad type m only appears in the return type, not in any of the arguments.

But it turns out that if you have an expression like

(a <|> b) >>= f

where m is a monad like [], then it’s always equivalent to

(a >>= f) <|> (b >>= f)

which means it is still algebraic

In contrast, most other common operations where m appears in the arguments are not algebraic, as they do not satisfy the above law.

Consider, for example, local and catch, which have the following types:

local :: MonadReader r m => (r -> r) -> m a -> m a
catch :: MonadError e m => m a -> (e -> m a) -> m a

If those operations were algebraic, the following laws would have to hold:

local f m >>= g  ==  local f (m >>= g)
catch m f >>= g  ==  catch (m >>= g) (f >=> g)

However, it is easy to see that these laws do not hold.

For example, local (+1) m >>= f increments the reader context by 1 inside m but not inside f, whereas local (+1) (m >>= f) uses the incremented context inside both m and f.

Example

If you have an stack of StateT and ExceptT together, algebraic operations (e.g. get, put, throw) are not affected by the order of composition.

But on non-algebraic operations (e.g. catch) the semantic vary depending on which order you stack the transformers.

Example: https://gist.github.com/monadplus/97c1f47d03689cee903f32f7e8dadf25

Credit

https://www.reddit.com/r/haskell/comments/ej8fme/unordered_effects/fd00mk2/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment