【问题标题】:Haskell Streams (Comonadic): Infinite?Haskell Streams(Comonadic):无限?
【发布时间】:2023-03-27 13:47:02
【问题描述】:

我已经看到流被用作共单子的默认示例,但我不太清楚它们是如何无限的,但不是。

假设我们有数据构造函数 (from here)

data Stream a = a :> Stream a

我们如何最终完成一个流?我们在最后写一个未定义的吗?我知道语言是懒惰的,但必须在某个地方切断结,对吧?我错了吗?

【问题讨论】:

  • 如果你完成了它就不再是无限的了吧?

标签: haskell stream lazy-evaluation infinite


【解决方案1】:

流本质上是无限的;你不能创建一个有限的流。比较StreamList

data List   a = Empty | a :  List a
data Stream a =         a :> Stream a

由于Empty 构造函数,您可以创建一个有限列表;可以在不引用另一个 List 值的情况下创建一个 List 值。另一方面,Stream 值只能使用另一个 Stream 值创建。 任何时候当你对Stream 进行模式匹配时,你会得到一个a 类型的值和另一个Stream 值。

“完成”一个流仅仅意味着您停止从中提取值,而不是您曾经到达流的“末端”。

实际上,这意味着您无法在内存中实例化完整的流;您只能按需构建它,通常是通过在 :> 构造函数上进行模式匹配时调用函数来生成流的剩余部分。

【讨论】:

  • 虽然在指称上完全合理,但最后一段(关于“在内存中实例化[ing]一个完整的流”)在操作上是不正确的——这正是打结给你的!例如,给定ones = 1 :> ones 的定义,流将由一个带有指向自身的指针的“cons”单元表示(一旦 thunk 消失)。
  • 一个更现实的场景是用户按下的按键流:您将其视为无限流,因为从来没有已知的按键是最后一个按键(忽略 ctrl-D现在)。终止发生在程序结束时,而不是流结束时。
  • @AntalSpector-Zabusky 可以很好地作为答案。另外,那么所有流都是循环的吗?
  • @JackBrandt 循环是在有限内存中表示概念上无限流的唯一方法(没有任何其他特定逻辑)。
  • @JackBrandt 您可以通过这种循环技术表示有限内存中的流。但是您不必:流nats = 0 :> fmap (+1) nats 是无限流0 :> 1 :> 2 :> …,但是如果您强制执行整个操作,它将占用无限内存。 (当然,除非你在路上把它当作垃圾收集了……)
猜你喜欢
  • 2016-01-27
  • 2016-09-11
  • 2017-09-28
  • 1970-01-01
  • 1970-01-01
  • 2013-10-05
  • 2011-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多