Jeśli mam EnumeratorT
odpowiedni odpowiednik IterateeT
, mogę je uruchomić razem:
val en: EnumeratorT[String, Task] = EnumeratorT.enumList(List("a", "b", "c"))
val it: IterateeT[String, Task, Int] = IterateeT.length
(it &= en).run : Task[Int]
Jeśli monada modułu wyliczającego jest „większa” niż monada iteracyjna, mogę użyć up
lub, bardziej ogólnie, Hoist
„podnieść” iterat, aby dopasować:
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]
Ale co mam zrobić, gdy monada iteracyjna jest „większa” niż monada wyliczająca?
val en: EnumeratorT[String, Id] = ...
val it: IterateeT[String, Task, Int] = ...
it &= ???
Wydaje się, że nie ma Hoist
instancji EnumeratorT
ani żadnej oczywistej metody „podnoszenia”.
Enumerator
tak naprawdę jest to tylko opakowanie wokółStepT => IterateeT
, co sugeruje, że musisz „ustąpić” od AStepT[E, BigMonad, A]
.Enumerator
jest tylko skutecznym źródłem, prawda? Wydaje mi się, że powinienem być w stanie użyć rzeczy, która może dostarczyćA
do zaopatrzeniaTask[A]
.Odpowiedzi:
W zwykłym kodowaniu moduł wyliczający to w zasadzie a
StepT[E, F, ?] ~> F[StepT[E, F, ?]]
. Jeśli spróbujesz napisać ogólną metodę konwertującą ten typ naStep[E, G, ?] ~> G[Step[E, G, ?]]
dany anF ~> G
, szybko napotkasz problem: musisz „obniżyć” aStep[E, G, A]
do aStep[E, F, A]
, aby móc zastosować oryginalny moduł wyliczający.Scalaz zapewnia również alternatywne kodowanie modułu wyliczającego, który wygląda następująco:
Takie podejście pozwala nam zdefiniować moduł wyliczający, który jest specyficzny dla potrzebnych efektów, ale który można „podnieść” do pracy z konsumentami, którzy wymagają bogatszych kontekstów. Możemy zmodyfikować twój przykład, aby używał
EnumeratorP
(i nowszego podejścia do naturalnej transformacji zamiast starej częściowej kolejności monady):Możemy teraz skomponować dwa w ten sposób:
EnumeratorP
jest monadycznego (jeśliF
jest aplikacyjnych), aEnumeratorP
obiekt towarzysz oferuje kilka funkcji, aby pomóc w określeniu rachmistrzów, które wyglądają trochę jak te naEnumeratorT
-Jestempty
,perform
,enumPStream
, itd. Myślę, że nie trzeba byćEnumeratorT
przypadki, które nie mogą być realizowane z wykorzystaniemEnumeratorP
kodowania, ale przy mojej głowie nie jestem pewien, co oni wyglądać.źródło