作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
作为 Scala 开发人员学习 IO Monad,因此一般来说 Trampolining 的技术对于无法进行尾调用优化的递归来说是必需的,我想知道 Haskell 似乎是如何自然地避免它的。
我知道 Haskell 是一种懒惰的语言,但是我想知道是否有人可以进一步详细说明。
例如,为什么 ForeverM stackoverflow 不在 Scala 中?好吧,我可以回答蹦床,我可以在库和博客中找到执行此操作的实际代码。我实际上自己实现了一个基本的蹦床来学习。
它在 Haskell 中是如何发生的?有没有办法稍微解开懒惰,提供一些指示,也许还有有助于更好地理解它的文档?
sealed trait IO[A] {
.....
def flatMap[B](f: A => IO[B]): IO[B] =
FlatMap[A,B](this, f) // we do not interpret the `flatMap` here, just return it as a value
def map[B](f: A => B): IO[B] =
flatMap[B](f andThen (Return(_)))
}
case class Return[A](a: A) extends IO[A]
case class Suspend[A](resume: () => A) extends IO[A]
case class FlatMap[A,B](sub: IO[A], k: A => IO[B]) extends IO[B]
......
@annotation.tailrec
def run[A](io: IO[A]): A = io match {
case Return(a) => a
case Suspend(r) => r()
case FlatMap(x, f) => x match {
case Return(a) => run(f (a))
case Suspend(r) => run(f( r()))
case FlatMap(y, g) => run(y flatMap (a => g(a) flatMap f))
}
}
最佳答案
函数式编程通常需要消除尾调用(否则函数调用的深层链会溢出堆栈)。例如,考虑这个偶数/奇数分类器的(效率极低的)实现:
def even(i: Int): Boolean =
if (i == 0) true
else if (i > 0) odd(i - 1)
else odd(i + 1)
def odd(i: Int): Boolean =
if (i == 0) false
else if (i > 0) even(i - 1)
else even(i + 1)
在这两个
even
和
odd
,每个分支要么是一个简单的表达式(在这种情况下是
true
或
false
),它不进行函数调用或尾部调用:被调用函数的值被返回而不被操作。
AIM-443
(可能需要
mit
或
steele
或
sussman
))称为“Lambda:The Ultimate”(这激发了这个名字的编程语言论坛)讨论了尾调用消除的含义以及这意味着函数式编程实际上对于解决现实世界的计算问题是可行的。
@tailrec
注释,您可能对它有些熟悉,它强制要求编译器能够执行尾调用消除。
关于scala - 为什么 Haskell 不需要蹦床?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67205343/
假设我正在尝试通过一个操作来实现一种非常简单的领域特定语言: printLine(line) 然后我想写一个接受整数 n 的程序作为输入,如果 n 打印一些东西可被 10k 整除,然后用 n + 1
我的目标是拦截来 self 没有源代码的定制应用程序的出站 TCP 数据包。我需要调整出站数据中的几个参数。这是一个较旧的应用程序,原来的公司不再销售并且开发人员不再可用。 所以我计划在 send()
我是一名优秀的程序员,十分优秀!