module Control.Effect.Coroutine (
EffectCoroutine, Coroutine, runCoroutine, suspend,
Iterator (..), evalIterator
) where
import Control.Monad.Effect
data Coroutine i o a = Coroutine (o -> a) i
deriving Functor
type instance Is Coroutine f = IsCoroutine f
type family IsCoroutine f where
IsCoroutine (Coroutine i o) = True
IsCoroutine f = False
class MemberEffect Coroutine (Coroutine i o) es => EffectCoroutine i o es
instance MemberEffect Coroutine (Coroutine i o) es => EffectCoroutine i o es
suspend :: EffectCoroutine i o es => i -> Effect es o
suspend = send . Coroutine id
runCoroutine :: Effect (Coroutine i o :+ es) a -> Effect es (Iterator i o es a)
runCoroutine = eliminate (return . Done) (\(Coroutine f k) -> return (Next f k))
data Iterator i o es a
= Done a
| Next (o -> Effect es (Iterator i o es a)) i
evalIterator :: Iterator i o es a -> [o] -> Effect es (Iterator i o es a, [i])
evalIterator (Next f v) (x:xs) = do
i <- f x
(r, vs) <- evalIterator i xs
return (r, v:vs)
evalIterator i _ = return (i, [])