Polysemy: Higher-order effects introductions

One thing that sets polysemy apart is that it allows defining Higher-order effects.

As higher-order functions, higher-order effects are effects defined in terms of other effects, let's try a simple one:

data When (m :: Type -> Type) a where
  WhenM :: m () -> When m ()

makeSem ''When

m () is the effect (it will be replaced by Sem _ ()).

In order to properly interpret this effect, we can rely on tactics.

interpretWhenEmbed :: InterpreterFor When r
interpretWhenEmbed =
  interpretH $
    \case
      WhenM act -> runTSimple act

Two elements have to be noticed:

  • interpretH gives a context to interpret higher-order effects
  • runTSimple which converts m () to the previously mentionned context (m is Sem rInitial and cannot be used directly)

finally, we can use it as any other interpreters:

runM $ interpretWhenEmbed $ whenM $ embed $ putStrLn "Hello,"

See the full the code here.