How would you make a monad instance of this coroutine?

I am Coroutine package for educational purposes, here it is:

 data Step abr = Stop | Yield br | Await (a -> r) instance Functor (Step ab) where fmap gs = case s of Stop -> Stop Yield br -> Yield b $ gr Await f -> Await (g . f) data CoroutineT mab = CoT { resume :: m (Step ab (CoroutineT mab)) } run_ :: Monad m => CoroutineT mab -> [a] -> m [b] run_ (CoT m) as = m >>= \step -> case step of Stop -> return [] Yield or -> liftM (o:) $ run_ r as Await k -> case is of [] -> return [] (x:xs) -> run_ (kx) xs instance Monad m => Functor (CoroutineT ma) where fmap g (CoT m) = CoT $ liftM ap m where ap Stop = Stop ap (Yield br) = Yield (gb) (fmap gr) ap (Await k) = Await $ (fmap g) . k instance Monad m => Monad (CoroutineT ma) where return b = CoT . return . Yield b $ return b (CoT m) >>= g = CoT $ liftM go m where go Stop = Stop go (Yield br) = undefined -- * This line I am having trouble with go (Await k) = Await $ (>>=g) . k 

As you can see in the comments above, the only line that I came across with the Yield event, I see that

 (>>=) :: CoroutineT mab -> (b -> CoroutineT mac) -> CoroutineT mac (gb) :: CoroutineT mac r :: CoroutineT mab (r >>= g) :: CoroutineT mac 

But I'm not sure

  • How to get them together so they print checks.
  • What is bind semantics in the case of Yield
+4
source share
2 answers

At the suggestion of Gabriel, an alternative implementation.

 data Step abxr = Done x | Yield br | Await (a -> r) | Fail instance Functor (Step abx) where fmap gs = case s of Done x -> Done x Yield br -> Yield b (gr) Await k -> Await $ g . k Fail -> Fail -- | note the monad type needs to parameterize over type of `x` in `Done x` data CoroutineT abmx = CoT { resume :: m (Step abx (CoroutineT abmx)) } instance Monad m => Functor (CoroutineT abm) where fmap g (CoT m) = CoT $ liftM ap m where ap (Done x) = Done $ gx ap (Yield br) = Yield b (fmap gr) ap (Await k) = Await $ (fmap g) . k ap Fail = Fail instance Monad m => Monad (CoroutineT abm) where return = CoT . return . Done (CoT m) >>= g = CoT $ m >>= \step -> case step of Done x -> resume $ gx Yield br -> return . Yield b $ r >>= g Await k -> return . Await $ (>>=g) . k Fail -> return Fail 

Note that implementing return now makes more sense.

+3
source

The base functor should be:

 data Step abrx = Stop r | Yield bx | Await (a -> x) 

... and your coroutine type should be:

 data CoroutineT mabr = CoT { resume :: m (Step abr (CoroutineT mabr)) } 

Until you make these two corrections, it will not work.

+4
source

Source: https://habr.com/ru/post/1495973/


All Articles