【问题标题】:Streams vs monads流与单子
【发布时间】:2012-05-07 21:44:10
【问题描述】:

流(惰性列表)和 monad 之间是否存在任何区别? 从概念和数学的角度,而不是从技术实现的角度。

否则,是否存在双唯一、一一对应关系?

更准确地说,作为流,它意味着来自 Scheme 语言的 SRFI-41 的“偶数流”。

它是不是 monads 之外的另一个类别?如果有,属于哪个类别?

“偶数流”可以保证对副作用的控制,比如单子?

【问题讨论】:

  • 据我了解,Scheme 的流是惰性值,而 Monad 是自定义的计算链。
  • 流完全是惰性列表。如何在没有 monad 或惰性列表或类似的东西的情况下呈现“惰性值”?不要将“惰性值”与不可变的函数变量混淆。那么,“自定义计算链”是否与“偶数流”一一对应?
  • 好吧。比较“偶数流”和 monad 的定义。还有他们的公理。据我所知,每个流都可以通过一个单子来表达。每个单子“值”或“计算”都可以通过“偶数流”表达,这是真的吗?有什么限制吗?
  • 惰性值只是延迟计算,Scheme 称之为承诺。 Monad 是以某种方式相互关联的计算(例如,它们需要是顺序的)。据我所知,这两个是不同的概念。
  • @Salil 但是什么是“延迟计算”(承诺)?在 SICP 中,据说“延迟”只是 lambda 的“语法糖”!而“力”只是平常的称呼!尽管它们的实现方式可能不同,但它们是以这种方式表达的。只是通常的价值观。尽管 monad 与“惰性值”的概念不同,但流也不同。因为它们是“惰性列表”。而且因为现在我们仍然没有定义什么是“惰性值”。延迟就是延迟,承诺就是承诺——这些是通常的价值观,而不是懒惰的。他们可能正在为懒惰构建元素,但他们自己并不懒惰。恕我直言。

标签: stream scheme monads categories lazy-evaluation


【解决方案1】:

正如 Salil 已经说过的,这两者是不同的概念:

是一个(可能是无限的)值列表,通常但不一定以惰性方式计算,即仅在请求时存储某种计算值的方式。周围有很多不涉及单子的例子:

(define integers (cons-stream 1 (stream-map (lambda (x) (+ x 1)) integers))

将有限的预先计算的列表也视为流非常有用,因为您可以在任何可以使用(可能或必然)有限惰性流的地方使用它们。

因此,流是具有操作next: streamType -> (valueType streamType) 以获取下一个值和剩余流的东西。

 

Monad,另一方面,与其说是一种数据结构,不如说是一种通过组合各个命令来编写源代码的方式。

可能最简单有用的例子是“Maybe monad”——我不确定它在 Scheme 中会是什么样子,抱歉,但想法是:给定一个计算列表 (f g h) 和一个输入 x,按顺序执行计算,几乎就像给定(f (g (h x))),但让每个函数优雅地失败:如果g 返回nil,则不要调用(f nil),而是立即返回nil

 

当然,您可以以各种有用的方式将两者结合起来,并使用 monad 计算您的流值,或者封装不完全符合 monad 中函数式编程期望的 I/O 流等流的使用(以避免存储对流的某些先前状态的引用的代码),但它们的用途完全不同。想想抽象层(关上盖子,不要看内部):一个monad,应用于函数,给你一个函数。另一方面,流不是更高的函数,而是值列表。

显然,由 monad 定义(或返回,取决于您的观点)的函数可以是流的实现,而且从流中提取的值也可以是 monad。但正如你在上面看到的,有一些 monad 实现了与流完全不同的东西。是否存在未实现为 monad 的流可能取决于您使用该术语的确切含义。我必须承认,目前我不确定无限流是否适合单子;有限列表显然可以。

【讨论】:

  • 您的回答更有用。对先前答案的反对并不反对任何区别。只是问题在于找出不同之处。但对先前答案的反对意见是反对“惰性值”与 Scheme 的承诺的等式。反对别的东西,但根本不反对任何区别。
  • 好吧,就在问题的文本中建议不要“隐藏”。那么,“数据结构”和“做某事的方式”(“编写代码”)之间的区别是什么?从时间和状态抽象的角度来看。说某事或多或少是一种“数据结构”。是“惰性列表”结构还是只是一种“方式”?因为“流完全是惰性列表”的声明只是对“惰性值”的反对。由此看来,流并不完全是“数据结构”。
  • 您对“更高功能”的推理更强大恕我直言。尽管它仍然需要证明没有任何方法可以将“偶数流”用作更高的功能。因此,可以证明流比 modad 更具限制性。但是要说它们完全不同,不要忘记流可以通过 monad 来表达。所以流只是单子的一个子类别。但是这个子类别是严格的“子”吗?还是只是部分交叉点?恕我直言,问题是开放的。
  • 为了避免在 cmets 中讨论,让我稍微修改一下我的答案。
  • 当然,请做任何你想要的版本。我是这里的新手,我不知道如何更好地在这里讨论 - 在 cmets 中或通过回答自己的问题。
猜你喜欢
  • 1970-01-01
  • 2011-02-26
  • 2017-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
相关资源
最近更新 更多