在箭头符号中,您可以使用rec关键字来编写递归定义。例如:
rec
name <- function -< input
input <- otherFunction -< name
这怎么能评估?它似乎只会进入一个无限循环或其他东西。我知道它评估循环箭头组合器,但我不明白它是如何工作的。
编辑:权力范例非常有用。但是你怎么用写符号来写呢?我假设您需要使用rec。答案 0 :(得分:23)
由于哈斯克尔斯的懒惰,这一点魔法起作用。您可能知道,Haskell会在需要时评估值,而不是在定义时。因此,如果您不需要直接或稍后输入的值,则此方法有效。
rec
是使用loop
的{{1}}函数实现的。它的定义如下:
ArrowLoop
您可以看到:输出仅作为输入反馈。它只会计算一次,因为Haskell只会在需要时评估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
。
以下是如何直接使用d
组合子的实际示例。此函数计算其参数的所有幂:
loop
(您也可以这样写:powers = loop $ \(x,l) -> (l,x:map(*x)l)
)
它是如何运作的?嗯,无限的权力列表在powers x = fix $ (x :) . map (*x)
参数中。评估看起来像这样:
l
答案 1 :(得分:12)
这是一个真实的例子:
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”。函数'loop f'取一个输入'b'并创建一个输出'c'。 'f'正在做的是研究'b'来产生'长度b',它将返回循环并绑定到'd'。
在“循环”中,这个'd =长度b'被输入'f',在那里它被用于计算中。
这对于构建不可变的双向链表(也可能是循环的)这样的技巧非常有用。对于遍历'b'一次既产生一些分析'd'(例如长度或最大元素)以及构建依赖于'd'的新结构'c'也是有用的。懒惰避免了必须两次遍历'b'。