gpt4 book ai didi

Scalaz 迭代器 : "Lifting" `EnumeratorT` to match `IterateeT` for a "bigger" monad

转载 作者:行者123 更新时间:2023-12-03 03:55:45 24 4
gpt4 key购买 nike

如果我有一个 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]

如果枚举器 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]

但是当 iteratee monad 比 enumerator monad “更大”时我该怎么办?

val en: EnumeratorT[String, Id] = ...
val it: IterateeT[String, Task, Int] = ...

it &= ???

似乎没有 EnumeratorTHoist 实例,也没有任何明显的“lift”方法。

最佳答案

在通常的编码中,枚举器本质上是一个StepT[E, F, ?] ~> F[StepT[E, F, ?]]。如果您尝试编写一个通用方法,在给定 F ~> G 的情况下将此类型转换为 Step[E, G, ?] ~> G[Step[E, G, ?]] ,您很快就会遇到一个问题:您需要将 Step[E, G, A]“降低”为 Step[E, F, A] 以便能够应用原始枚举器。

Scalaz 还提供 an alternative enumerator encoding看起来像这样:

trait EnumeratorP[E, F[_]] {
def apply[G[_]: Monad](f: F ~> G): EnumeratorT[E, G]
}

这种方法使我们能够定义一个枚举器,该枚举器特定于其所需的效果,但可以“提升”以与需要更丰富上下文的消费者一起使用。我们可以修改您的示例以使用 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) }

我们现在可以像这样组合两者:

scala> def result = (iter &= enum(toTask)).run
result: scalaz.concurrent.Task[Int]

EnumeratorP 是一元的(如果 F 是适用的),并且 EnumeratorP 伴随对象提供了一些函数来帮助定义看起来像的枚举器很像 EnumeratorT 上的那些 - 有 emptyperformenumPStream 等。我想必须有是无法使用 EnumeratorP 编码实现的 EnumeratorT 实例,但我无法确定它们会是什么样子。

关于Scalaz 迭代器 : "Lifting" `EnumeratorT` to match `IterateeT` for a "bigger" monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26914692/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com