Dans l'article "Coroutine Pipelines" dans Monad.Reader Issue 19, l'auteur définit un type Coroutine
générique:quelle est la relation entre type Freet de Haskell et Coroutine
newtype Coroutine f m a = Coroutine
{ resume :: m (Either (f (Coroutine f m a)) a)
}
Je remarque que c'est très similaire au type FreeT
de l'emballage free
:
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))
}
Il semble que FreeT
et Coroutine
sont isomorphes. Voici la mise en correspondance des fonctions de l'un à l'autre:
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
je les questions suivantes:
- Quelle est la relation entre les types
FreeT
etCoroutine
? Pourquoi l'auteur de "Coroutine Pipelines" n'a-t-il pas utilisé le typeFreeT
au lieu de créer le typeCoroutine
? - Existe-t-il une sorte de relation plus profonde entre les monades libres et les coroutines? Cela ne semble pas une coïncidence si les types sont isomorphes.
Pourquoi les bibliothèques de streaming populaires dans Haskell ne sont-elles pas basées sur
FreeT
?Le type de données de base dans
pipes
estProxy
: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 r
Le type de données de base dans
conduit
estPipe
: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) l
J'imagine qu'il serait possible d'écrire les
Proxy
ouPipe
types de données à base autourFreeT
, alors je me demande pourquoi ce n'est pas fait? Est-ce pour des raisons de performance?Le seul indice de
FreeT
que j'ai vu dans les bibliothèques de diffusion populaires est pipes-group, qui utiliseFreeT
pour regrouper des éléments dans les flux.
Je pense que la raison pour laquelle l'article Monad.Reader et les bibliothèques de streaming n'utilisent pas 'FreeT' est la même: cela ne vous rapporte rien. Dans le cas de l'article, je suppose que l'auteur a estimé que le code était plus clair et plus autonome tel qu'il apparaît dans l'article. Dans le cas des bibliothèques, pourquoi avoir une dépendance sur 'free' (et, transitif, un gros morceau de la plate-forme Kmett) quand vous pouvez faire le travail sans elle? IOW: oui, 'FreeT' supporte une classe de types de coroutine mais cela ne signifie pas qu'un coroutine donné _must_ soit implémenté en utilisant' FreeT'; préoccupations d'ingénierie ennuyeuses ont priorité –
Merci @BenjaminHodgson. Je pense que votre commentaire répond bien à mes questions 1 et 3. Je me pose encore des questions sur ma question 2. Existe-t-il une relation plus profonde entre les coroutines et les monades libres? – illabout
Pour la question 3, j'ai trouvé un commentaire sur la reddit de @ gabriel-gonzalez (l'auteur de 'pipes'): https://www.reddit.com/r/haskell/comments/23m4bs/i_added_a_coroutine_example_to_the_wiki_did_i/cgyfxux/ Il dit que «tuyaux» est destiné à être relativement simple et facile à lire. Avec les problèmes d'utilisation de la bibliothèque, c'est en partie la raison pour laquelle 'pipes' n'utilise pas la transformation de la codensité. J'imagine que cela pourrait aussi faire partie de la raison pour laquelle il n'est pas basé sur 'FreeT'. Ce serait plus difficile à comprendre sans (?) Bénéfice réel. – illabout