【问题标题】:Why is the Empty input case needed in Scala Iteratees?为什么 Scala Iteratees 需要 Empty 输入用例?
【发布时间】:2013-06-25 00:43:40
【问题描述】:

我见过的 Scala 中 Iteratee 模式的 3 个描述都包括 3 个输入用例。例如,来自詹姆斯:

sealed trait Input[+E]
object Input {
  case object EOF extends Input[Nothing]
  case object Empty extends Input[Nothing]
  case class El[+E](e: E) extends Input[E]
}

更多详情请参阅JamesRunarJosh 的博客。

我的问题很简单:为什么正是需要 Empty 输入案例?

迭代模式定义了值流的生产者和消费者之间的关系。直观地说,如果任何输入为空,“运行”迭代器的生产者应该简单地折叠该空项,并且在非空输入可用之前不调用迭代器。

我注意到基于 pull 的 iteratees 类比,更熟悉的迭代器,不定义空案例,尽管元素可能已被过滤掉“内部”迭代器。

trait Iterator[E] {
    next: E        // like El
    hasNext: Boolean  //like EOF
}

虽然上述所有博客都提到需要空输入,但他们没有明确讨论为什么不能完全消除它。我注意到显示的示例迭代器将空输入视为无操作。

我真的很想要一个带有代码的示例,说明一个看似合理的“现实世界”问题,需要 Empty 输入消息来解决。

【问题讨论】:

  • 对 monad / applicative 法则的呼吁是否不够“真实世界”?试着想想如果没有Empty,你将如何为Iteratee[E, _] 定义pure
  • @TravisBrown, pure(a: A) = Done(a)?我会从那里开始,看看它是否有效。
  • @huynhjl:Done 的构造函数有两个参数,如果看起来有一个只有一个的重载版本,那是因为第二个默认为 Empty
  • @TravisBrown,但如果 iteratee 库设计为使用只有一个参数且没有 Empty 作为 Input 构造函数之一的 Done,我的感觉是您仍然可以定义pure、map 和 flatMap 并让 Iteratee[E, _] 成为一个单子。因此,这不是输入空的动机。

标签: scala iterate


【解决方案1】:

假设您连接了一个枚举器,它将一些元素提供给peek iteratee,该迭代器查看第一个元素并返回它但不消耗它,让它可能由另一个可能与@987654325 组成的迭代器使用@。然后你会想为peek 提供一种机制来放回元素。从 Play 和 Scalaz iteratee 中我可以看出,done iteratee 只为此目的接受了一个参数。所以你可以用伪代码做一些事情:done(Some(result), El(result))。见this implementation of peek

现在,如果您实现类似head 之类的东西,它实际上会消耗元素,那么感觉一种方法是返回done(Some(result), emptyInput) 以指示输入已被消耗。

另请参阅 playframework 源代码中的 this comment,显示 Done(_, _) 的第二个参数用于未使用的输入并初始化为空默认值。如此空旷的东西很少使用,很难找到现实世界的例子。它确实是实现迭代器的关键。事实上,看看哪些 iteratee 框架没有 empty 以及它们如何实现 peek 和 head 可能会很有趣。

【讨论】:

    【解决方案2】:

    James Roper 给出了有用的回复here,包括我觉得有趣的这个 sn-p:

    我猜另一种可以实现的方式是使用 Option[Input] 作为完成的剩余输入。这将使实施 迭代更简单,因为它们不需要处理空。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-14
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      • 2015-05-17
      • 2021-10-17
      • 2019-08-26
      • 1970-01-01
      相关资源
      最近更新 更多