scala Scalaz iteratees:“提升”`EnumeratorT` 以匹配`IterateeT` 以获得“更大”的monad
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26914692/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scalaz iteratees: "Lifting" `EnumeratorT` to match `IterateeT` for a "bigger" monad
提问by lmm
If I have an EnumeratorTand a corresponding IterateeTI can run them together:
如果我有一个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]
If the enumerator monad is "bigger" than the iteratee monad, I can use upor, more generally, Hoistto "lift" the iteratee to match:
如果枚举器 monad 比 iteratee monad“大”,我可以使用up或更一般Hoist地“提升” iteratee 以匹配:
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]
But what do I do when the iteratee monad is "bigger" than the enumerator monad?
但是当 iteratee monad 比 enumerator monad“大”时我该怎么办?
val en: EnumeratorT[String, Id] = ...
val it: IterateeT[String, Task, Int] = ...
it &= ???
There doesn't seem to be a Hoistinstance for EnumeratorT, nor any obvious "lift" method.
似乎没有Hoist实例EnumeratorT,也没有任何明显的“提升”方法。
采纳答案by Travis Brown
In the usual encoding an enumerator is essentially a StepT[E, F, ?] ~> F[StepT[E, F, ?]]. If you try to write a generic method converting this type into a Step[E, G, ?] ~> G[Step[E, G, ?]]given an F ~> G, you'll quickly run into an issue: you need to "lower" a Step[E, G, A]to a Step[E, F, A]in order to be able to apply the original enumerator.
在通常的编码中,枚举器本质上是一个StepT[E, F, ?] ~> F[StepT[E, F, ?]]. 如果您尝试编写一个将这种类型转换为Step[E, G, ?] ~> G[Step[E, G, ?]]给定 an的通用方法F ~> G,您将很快遇到一个问题:您需要将 a “降低”Step[E, G, A]到 aStep[E, F, A]以便能够应用原始枚举数。
Scalaz also provides an alternative enumerator encodingthat looks like this:
Scalaz 还提供了一种替代的枚举器编码,如下所示:
trait EnumeratorP[E, F[_]] {
def apply[G[_]: Monad](f: F ~> G): EnumeratorT[E, G]
}
This approach allows us to define an enumerator that's specific about the effects it needs, but that can be "lifted" to work with consumers that require richer contexts. We can modify your example to use EnumeratorP(and the newer natural transformation approach rather than the old monad partial order):
这种方法允许我们定义一个枚举器,它特定于它需要的效果,但可以“提升”以与需要更丰富上下文的消费者一起工作。我们可以修改您的示例以使用EnumeratorP(以及更新的自然转换方法而不是旧的 monad 偏序):
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) }
We can now compose the two like this:
我们现在可以像这样组合两者:
scala> def result = (iter &= enum(toTask)).run
result: scalaz.concurrent.Task[Int]
EnumeratorPis monadic (if the Fis applicative), and the EnumeratorPcompanion object provides some functions to help with defining enumerators that look a lot like the ones on EnumeratorT—there's empty, perform, enumPStream, etc. I guess there have to be EnumeratorTinstances that couldn't be implemented using the EnumeratorPencoding, but off the top of my head I'm not sure what they would look like.
EnumeratorP是 monadic(如果F是适用的),并且EnumeratorP伴随对象提供了一些函数来帮助定义枚举器,这些枚举器看起来很像EnumeratorT- there 's empty, perform, enumPStream, 等等。我想必须有一些EnumeratorT实例无法使用该EnumeratorP编码,但是从我的头顶,我不知道他们是什么样子。

