fumieval / extensible

Extensible records, variants, structs, effects, tangles
BSD 3-Clause "New" or "Revised" License
128 stars 20 forks source link

[question]How to implement a standard effect handler? #9

Closed myuon closed 7 years ago

myuon commented 7 years ago

I want to implement an effect handler, using operation pattern-matching with continuations. For example, here is a simple state example:

interface State s = Get : s | Put : s -> ()

state : Eff [State a] r -> a -> r
state = \case
  value r -> \_ -> r
  <Get -> k> -> \s -> state (k s) s
  <Put s' -> k> -> \_ -> state (k ()) s'

In this example, type of the two continuation k in case pattern should be a -> Eff [State a] r and () -> Eff [State a] r.

However, peelEff has type Rebinder xs r -> (a -> r) -> (forall x. t x -> (x -> r) -> r) -> Eff ((k >: t) ': xs) a -> r, this seems not fit in this example. The type of operation handling function should be forall x. t x -> (x -> Eff xs r) -> r.

So how to implement this effect handler in extensible?

fumieval commented 7 years ago

Is peelEff1 what you want?


data GetPut s a where
   Get :: GetPut s s
   Put :: s -> GetPut s ()

runGetPut :: Eff ((k >: GetPut s) ': r) a -> s -> Eff r (a, s)
runGetPut = peelEff1 (\a s -> return (a, s))
  $ \t k s -> case t of
    Get -> k s s
    Put s' -> k () s'
myuon commented 7 years ago

Oh, Great! I just didn't understand how peelEff works. Thanks :smiley: