7 | | The framework relies on the [wiki:monad-parallel monad-parallel] package to enable parallel execution of multiple coroutines' steps. |

8 | | |

9 | | == The lowest layer: trampoline-style nestable coroutines == |

10 | | |

11 | | This layer, implemented by the Control.Concurrent.Coroutine module, provides a limited coroutine functionality in Haskell. The centerpiece of the approach is the monad transformer Coroutine, that transforms an arbitrary monadic computation into a suspendable and resumable one. The basic definition is simple: |

12 | | |

13 | | {{{ |

14 | | newtype Coroutine s m r = Coroutine {resume :: m (CoroutineState s m r)} |

15 | | |

16 | | data CoroutineState s m r = Done r | Suspend! (s (Coroutine s m r)) |

17 | | |

18 | | instance (Functor s, Monad m) => Monad (Coroutine s m) where |

19 | | return x = Coroutine (return (Done x)) |

20 | | t >>= f = Coroutine (resume t >>= apply f) |

21 | | where apply f (Done x) = resume (f x) |

22 | | apply f (Suspend s) = return (Suspend (fmap (>>= f) s)) |

23 | | }}} |

24 | | |

25 | | The Coroutine transformer type is parameterized by a functor. Here is an example of one functor particularly useful for a Coroutine computation: |

26 | | |

27 | | {{{ |

28 | | data Yield x y = Yield x y |

29 | | instance Functor (Yield x) where |

30 | | fmap f (Yield x y) = Yield x (f y) |

31 | | }}} |

| 7 | The framework relies on the following packages: |

| 8 | * [wiki:monad-parallel monad-parallel] to enable parallel execution of monadic computations, and |

| 9 | * [wiki:monad-coroutine monad-coroutine] to enable the same monadic computations to suspend and resume each other. |