내가 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]
열거 자 모나드가 iteratee 모나드보다 “더 큰”경우 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]
그러나 iteratee 모나드가 열거 자 모나드보다 “더 큰”경우 어떻게해야합니까?
val en: EnumeratorT[String, Id] = ...
val it: IterateeT[String, Task, Int] = ...
it &= ???
에 대한 Hoist
인스턴스 EnumeratorT
나 명백한 “리프트”방법 이없는 것 같습니다 .
답변
일반적인 인코딩에서 열거자는 본질적으로 StepT[E, F, ?] ~> F[StepT[E, F, ?]]
입니다. 이 형식을 Step[E, G, ?] ~> G[Step[E, G, ?]]
지정된 형식으로 변환하는 일반 메서드를 작성하려고 F ~> G
하면 문제가 발생합니다. 원래 열거자를 적용하려면 a Step[E, G, A]
를 “낮게”해야합니다 Step[E, F, A]
.
Scalaz는 다음과 같은 대체 열거 형 인코딩 도 제공 합니다 .
trait EnumeratorP[E, F[_]] {
def apply[G[_]: Monad](f: F ~> G): EnumeratorT[E, G]
}
이 접근 방식을 사용하면 필요한 효과에 대해 구체적인 열거자를 정의 할 수 있지만 더 풍부한 컨텍스트가 필요한 소비자와 함께 작업하기 위해 “리프팅”할 수 있습니다. 우리는 사용하기 위해 당신의 예제를 수정할 수 있습니다 EnumeratorP
(그리고 오래된 모나드 부분 순서가 아닌 새로운 자연 변환 접근법).
import scalaz._, Scalaz._, iteratee._, concurrent.Task
def enum: EnumeratorP[String, Id] = ???
def iter: IterateeT[String, Task, Int] = ???
val toTask = new (Id ~> Task) { def apply[A](a: A): Task[A] = Task(a) }
이제 다음과 같이 두 가지를 구성 할 수 있습니다.
scala> def result = (iter &= enum(toTask)).run
result: scalaz.concurrent.Task[Int]
EnumeratorP
합니다 (이 경우 모나드이다 F
실용적이다), 그리고 EnumeratorP
동반자 개체에있는 것과 같은 많은 모양 열거 정의하는 데 도움이되는 몇 가지 기능을 제공 EnumeratorT
저기의를 empty
, perform
, enumPStream
, 등 내가 거기 추측해야 EnumeratorT
사용하여 구현 할 수없는 경우 EnumeratorP
인코딩,하지만 내 머리 위로 떨어져 나는 확실히 그들이 어떻게 보이는지 모르겠어요.