Haskell rec关键字是如何工作的?

Haskell rec关键字是如何工作的?,haskell,arrows,Haskell,Arrows,在arrow-do表示法中,可以使用rec关键字编写递归定义。例如: rec name <- function -< input input <- otherFunction -< name rec name由于哈斯凯尔的懒惰,这一点魔法奏效了。您可能知道,Haskell在需要时计算值,而不是在定义时。因此,如果您不需要直接输入值,或者稍后输入值,那么这是可行的 rec是使用ArrowLoop的loop功能实现的。其定义如下: class Arrow a

在arrow-do表示法中,可以使用rec关键字编写递归定义。例如:

rec
    name <- function -< input
    input <- otherFunction -< name
rec

name由于哈斯凯尔的懒惰,这一点魔法奏效了。您可能知道,Haskell在需要时计算值,而不是在定义时。因此,如果您不需要直接输入值,或者稍后输入值,那么这是可行的

rec
是使用
ArrowLoop
loop
功能实现的。其定义如下:

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
您可以看到:输出只是作为输入进行反馈。它将只计算一次,因为Haskell只在需要时计算
d

下面是一个如何直接使用
循环
组合器的实际示例。此函数计算其参数的所有幂:

powers = loop $ \(x,l) -> (l,x:map(*x)l)
(您也可以这样编写:
powers x=fix$(x:).map(*x)

它是如何工作的?嗯,无穷多的幂列在
l
参数中。评估结果如下所示:

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

下面是一个真实的例子:

loop f b = let (c,d) = f (b,d) in c

f (b,d) = (drop (d-2) b, length b)

main = print (loop f "Hello World")
该程序输出“ld”。函数“循环f”接受一个输入“b”,并创建一个输出“c”。“f”所做的是研究“b”以产生“长度b”,它将返回到循环并绑定到“d”

在“循环”中,该“d=长度b”被输入到“f”中,并在下降计算中使用


这对于构建不可变的双链表(也可能是循环的)之类的技巧非常有用。遍历“b”一次也很有用,既可以生成一些分析“d”(如长度或最大元素),也可以构建依赖于“d”的新结构“c”。懒惰避免了两次遍历“b”。

我理解这一点,但它从哪里获得第一个输出样本?是否在某个地方定义了基本情况,因为我还没有看到。如果在我的示例中既没有提供输入也没有提供名称,那么该如何计算呢?或者必须提供这两个参数中的一个?诀窍是Haskell不会计算未使用的参数。只是控制流没有必要像您所想的那样。在计算输出“d”时,“f(b,)”必须只使用输入“b”f'在构建“c”时可以同时使用“b”和“d”,只要它不会强制对“d”的求值导致其挂起。你可以这样想:当‘c’被强制时,它会导致‘d’从‘b’计算出来,然后‘c’从‘b’和‘d’计算出来。@Chris Kuklewicz:不总是这样。考虑这样一个函数:
f=loop$\(x,l)->(l,x:map(*x)l)
。这将进行评估,因为您只使用了
l
@JeffBurka中已经定义的元素,我不确定这是do标记法的一个很好的示例,但我认为powers示例大致相当于:
powers=proc x->do{rec{l任何人以前都没有听说过
rec