Haskell rec 关键字如何工作?
在箭头do表示法中,您可以使用rec关键字来编写递归定义。举例来说:
rec
name <- function -< input
input <- otherFunction -< name
这如何评估?看起来它会进入无限循环或其他什么。我知道它的计算结果为循环箭头组合器,但我也不明白它是如何工作的。
编辑:那个权力的例子真的很有帮助。不过,你会如何用 do 符号来写它呢?我假设你需要使用rec.
In arrow do notation, you can use the rec keyword to write recursive definitions. So for example:
rec
name <- function -< input
input <- otherFunction -< name
How can this ever evaluate? It seems like it would just go into an infinite loop or something. I know it evaluates to the loop arrow combinator, but I don't understand how that works either.
EDIT: that powers example is really helpful. How would you write that with do notation, though? I assume you would need to use rec.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这种神奇的效果是由于 haskells 的懒惰造成的。您可能知道,Haskell 在需要时计算值,而不是在定义时计算值。因此,如果您不需要直接输入值或稍后输入值,则此方法有效。
rec
是使用ArrowLoop
的loop
函数实现的。其定义如下:可以看到:输出只是作为输入反馈回来的。它只会被计算一次,因为 Haskell 只会在需要时计算 d 。
这是如何直接使用
loop
组合器的实际示例。该函数计算其参数的所有幂:(您也可以这样写:
powers x = fix $ (x :) .map (*x)
)它是如何工作的?那么,无限的权力列表就在
l
参数中。评价看起来像这样:This bit of magic works due to haskells laziness. As you might know, Haskell evaluates a value when needed, not when defined. Thus, this works if you don't need the value fed in directly, or maybe later.
rec
is implemented using theloop
function ofArrowLoop
. It is defined as followed:You can see: The output is just fed back as the input. It will be calculated just once, because Haskell will only evaluate
d
when it's needed.Here's an actual example of how to use the
loop
combinator directly. This function calculates all the powers of it's argument:(You could also write it like this instead:
powers x = fix $ (x :) . map (*x)
)How does it works? Well, the infinite list of powers is in the
l
argument. The evaluation looks like this:这是一个真实的例子:
这个程序输出“ld”。函数“loop f”接受一个输入“b”并创建一个输出“c”。 “f”正在做的是研究“b”以产生“长度b”,该长度返回到循环并绑定到“d”。
在“循环”中,这个“d=长度b”被输入到“f”中,在“f”中用于drop的计算。
这对于构建不可变的双向链表(也可能是循环的)等技巧很有用。它对于遍历“b”一次以产生一些分析“d”(例如长度或最大元素)并构建依赖于“d”的新结构“c”也很有用。惰性避免了必须遍历“b”两次。
Here is a real-ish example:
This program outputs "ld". The function 'loop f' takes one input 'b' and creates one output 'c'. What 'f' is doing is studying 'b' to produce 'length b' which is getting returned to loop and bound to 'd'.
In 'loop' this 'd=length b' is fed into the 'f' where it is used in the calculation in drop.
This is useful for tricks like building an immutable doubly linked list (which may also be circular). It is also useful for traversing 'b' once to both produce some analytic 'd' (such as length or biggest element) and to build a new structure 'c' that depends on 'd'. The laziness avoids having to traverse 'b' twice.