Если у меня есть EnumeratorT
и соответствующий, IterateeT
я могу запустить их вместе:
val en: EnumeratorT[String, Task] = EnumeratorT.enumList(List("a", "b", "c"))
val it: IterateeT[String, Task, Int] = IterateeT.length
(it &= en).run : Task[Int]
Если монада перечислителя "больше", чем монада итерируемого, я могу использовать up
или, в более общем смысле, Hoist
"поднять" итератора для сопоставления:
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]
Но что мне делать, если итеративная монада "больше", чем монада перечислителя?
val en: EnumeratorT[String, Id] = ...
val it: IterateeT[String, Task, Int] = ...
it &= ???
Кажется , нет ни одного Hoist
примера EnumeratorT
, ни какого-либо очевидного метода «подъема».
Enumerator
самом деле это просто обертка вокруг aStepT => IterateeT
, которая предполагает, что вам нужно «уйти в отставку» отStepT[E, BigMonad, A]
.Enumerator
просто эффективный источник, верно? Такое чувство, что я должен быть в состоянии использовать то, что может поставитьA
для снабженияTask[A]
.Ответы:
В обычном кодировании перечислитель по сути является
StepT[E, F, ?] ~> F[StepT[E, F, ?]]
. Если вы попытаетесь написать универсальный метод, преобразующий этот тип вStep[E, G, ?] ~> G[Step[E, G, ?]]
данноеF ~> G
, вы быстро столкнетесь с проблемой: вам нужно «опустить» aStep[E, G, A]
доStep[E, F, A]
, чтобы иметь возможность применить исходный перечислитель.Scalaz также предоставляет альтернативную кодировку перечислителя, которая выглядит следующим образом:
Этот подход позволяет нам определять перечислитель, который конкретно определяет необходимые эффекты, но его можно «поднять» для работы с потребителями, которым требуется более широкий контекст. Мы можем изменить ваш пример для использования
EnumeratorP
(и более новый подход к естественному преобразованию, а не старый частичный порядок монад):Теперь мы можем составить два, как это:
EnumeratorP
является монадическим (еслиF
это аппликативно), аEnumeratorP
объект компаньона предоставляет некоторые функции , чтобы помочь с определением счетчиков , которые очень похожи на те , наEnumeratorT
-ТАХempty
,perform
,enumPStream
и т.д. Я думаю , там должен бытьEnumeratorT
случаями , которые не могут быть реализованы с использованиемEnumeratorP
кодирование, но с верхней части моей головы , я не уверен , что они будут выглядеть.источник