In the "Coroutine Pipelines" article in Monad.Reader Issue 19, the author defines a generic Coroutine type:
newtype Coroutine f m a = Coroutine
{ resume :: m (Either (f (Coroutine f m a)) a)
}
I noticed that this type is very similar to the FreeT type from the free package:
data FreeF f a b = Pure a | Free (f b)
newtype FreeT f m a = FreeT
{ runFreeT :: m (FreeF f a (FreeT f m a))
}
It seems that FreeT and Coroutine are isomorphic. Here are the functions mapping from one to the other:
freeTToCoroutine
:: forall f m a. (Functor f, Functor m) => FreeT f m a -> Coroutine f m a
freeTToCoroutine (FreeT action) = Coroutine $ fmap f action
where
f :: FreeF f a (FreeT f m a) -> Either (f (Coroutine f m a)) a
f (Pure a) = Right a
f (Free inner) = Left $ fmap freeTToCoroutine inner
coroutineToFreeT
:: forall f m a. (Functor f, Functor m) => Coroutine f m a -> FreeT f m a
coroutineToFreeT (Coroutine action) = FreeT $ fmap f action
where
f :: Either (f (Coroutine f m a)) a -> FreeF f a (FreeT f m a)
f (Right a) = Pure a
f (Left inner) = Free $ fmap coroutineToFreeT inner
I have the following questions:
- What is the relationship between the
FreeTandCoroutinetypes? Why didn't the author of "Coroutine Pipelines" use theFreeTtype instead of creating theCoroutinetype? - Is there some sort of deeper relationship between free monads and coroutines? It doesn't seem like a coincidence that the types are isomorphic.
Why aren't popular streaming libraries in Haskell based around
FreeT?The core datatype in
pipesisProxy:data Proxy a' a b' b m r = Request a' (a -> Proxy a' a b' b m r ) | Respond b (b' -> Proxy a' a b' b m r ) | M (m (Proxy a' a b' b m r)) | Pure rThe core datatype in
conduitisPipe:data Pipe l i o u m r = HaveOutput (Pipe l i o u m r) (m ()) o | NeedInput (i -> Pipe l i o u m r) (u -> Pipe l i o u m r) | Done r | PipeM (m (Pipe l i o u m r)) | Leftover (Pipe l i o u m r) lI imagine it would be possible to write the
ProxyorPipedatatypes based aroundFreeT, so I wonder why it is not done? Is it for performance reasons?The only hint of
FreeTI've seen in the popular streaming libraries is pipes-group, which usesFreeTto group items in streams.