Haskell rec关键字如何工作? [英] How does the Haskell rec keyword work?
问题描述
在箭头符号中,可以使用rec关键字来编写递归定义。例如:
rec
name< - function - <输入
input< - otherFunction - <名称
如何评估?它似乎会进入一个无限循环或什么东西。我知道它评估到循环箭头组合器,但我不明白它是如何工作的。
编辑:该权力示例是非常有用的。尽管如此,你会如何写这个符号?我假设你需要使用rec。
由于haskells懒惰,这一点魔法有效。正如您可能知道的那样,Haskell在需要时评估一个值,而不是在定义时评估。因此,如果你不需要直接输入的价值,或者稍后输入价值,那么这就很有效。
rec
是使用 ArrowLoop
的循环
函数实现。它定义如下:
class Arrow a => ArrowLoop a其中
loop :: a(b,d)(c,d) - > abc
实例ArrowLoop( - >)其中
loop fb = let(c,d)= f(b,d)in c
您可以看到:输出仅作为输入反馈。它只会计算一次,因为Haskell只会在需要时评估 d
。
下面是一个实际的例子如何直接使用循环
组合子。这个函数计算它的参数的所有权力:
powers = loop $ \(x,l) - > (l,x:map(* x)l)
<你也可以这样写: powers x = fix $(x :)。map(* x)
)
那么,权力的无限列表在 l
参数中。评估如下:
pre $ power $ loop $ \(x,l) - > (l,x:map(* x)l)==> (c,d)=(\(x,l) - >(l,x:map(* x)l))(b,d)在c ==>
幂b = let(c,d)=(d,b:map(* b)d)in d ==> - 现在我们用2作为参数
幂2 = let(c,d)=(d,2:map(* 2)d)in d ==> (c,(2:d))=(d,2:map(* 2)d)in c ==> (c,(2:4:d))=((2:d),2:映射(* 2)(2:d)) $()()=((2:4:d),2:map(* 2)(2:4:d))in ==> - 等等
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.
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 the loop
function of ArrowLoop
. It is defined as followed:
class Arrow a => ArrowLoop a where
loop :: a (b,d) (c,d) -> a b c
instance ArrowLoop (->) where
loop f b = let (c,d) = f (b,d) in c
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:
powers = loop $ \(x,l) -> (l,x:map(*x)l)
(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:
powers = loop $ \(x,l) -> (l,x:map(*x)l) ==>
powers b = let (c,d) = (\(x,l) -> (l,x:map(*x)l)) (b,d) in c ==>
powers b = let (c,d) = (d,b:map(*b)d) in d ==> -- Now we apply 2 as an argument
powers 2 = let (c,d) = (d,2:map(*2)d) in d ==>
= let (c,(2:d)) = (d,2:map(*2)d) in c ==>
= let (c,(2:4:d)) = ((2:d),2:map(*2)(2:d)) in c ==>
= let (c,(2:4:8:d)) = ((2:4:d),2:map(*2)(2:4:d)) in ==> -- and so on
这篇关于Haskell rec关键字如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!