Si tengo un EnumeratorT
y un correspondiente IterateeT
, puedo ejecutarlos juntos:
val en: EnumeratorT[String, Task] = EnumeratorT.enumList(List("a", "b", "c"))
val it: IterateeT[String, Task, Int] = IterateeT.length
(it &= en).run : Task[Int]
Si la mónada enumeradora es "más grande" que la mónada iterada, puedo usar up
o, más generalmente, Hoist
para "levantar" la iteración para que coincida:
val en: EnumeratorT[String, Task] = ...
val it: IterateeT[String, Id, Int] = ...
val liftedIt = IterateeT.IterateeTMonadTrans[String].hoist(
implicitly[Task |>=| Id]).apply(it)
(liftedIt &= en).run: Task[Int]
Pero, ¿qué hago cuando la mónada iteratee es "más grande" que la mónada enumeradora?
val en: EnumeratorT[String, Id] = ...
val it: IterateeT[String, Task, Int] = ...
it &= ???
No parece haber una Hoist
instancia EnumeratorT
ni un método obvio de "elevación".
Enumerator
realidad es solo una envoltura alrededor de aStepT => IterateeT
, lo que sugiere que tendrá que "renunciar" de aStepT[E, BigMonad, A]
.Enumerator
es solo una fuente efectiva, ¿verdad? Parece que debería poder usar algo que puede suministrarA
para suministrarTask[A]
.Respuestas:
En la codificación habitual, un enumerador es esencialmente a
StepT[E, F, ?] ~> F[StepT[E, F, ?]]
. Si intenta escribir un método genérico que convierta este tipo en unStep[E, G, ?] ~> G[Step[E, G, ?]]
dadoF ~> G
, rápidamente se encontrará con un problema: debe "bajar" aStep[E, G, A]
aStep[E, F, A]
para poder aplicar el enumerador original.Scalaz también proporciona una codificación de enumerador alternativa que se ve así:
Este enfoque nos permite definir un enumerador que sea específico sobre los efectos que necesita, pero que puede "levantarse" para trabajar con consumidores que requieren contextos más ricos. Podemos modificar su ejemplo para usar
EnumeratorP
(y el nuevo enfoque de transformación natural en lugar del antiguo orden parcial de mónada):Ahora podemos componer los dos así:
EnumeratorP
es monádica (si elF
es aplicativo), y elEnumeratorP
objeto acompañante proporciona algunas funciones para ayudar con la definición de los encuestadores que se parecen mucho a los que están enEnumeratorT
-Hayempty
,perform
,enumPStream
, etc supongo que tiene que haberEnumeratorT
instancias que no se podrían aplicar aprovechando laEnumeratorP
codificación, pero fuera de mi cabeza no estoy seguro de cómo se verían.fuente