22

ArrowLoop包含的函数实例

loop :: ((b,d) -> (c,d)) -> (b -> c)
loop f b = let (c,d) = f (b,d) in c

首先我对签名有一个问题:我们怎么可能b -> c(b,d) -> (c,d)? 我的意思是,c结果元组中的 可能取决于输入的两个元素,如何“切断” 的影响d

其次,我不明白let这里的工作原理。不包含(c,d) = f (b,d)的循环定义d?从哪里来d?老实说,我很惊讶这是有效的语法,因为看起来我们会重新定义d.

我的意思是在数学中这是有道理的,例如 f 可能是一个复杂的函数,但我只会提供实部 b,并且我需要选择虚部 d 以使其在我不会改变时评估 f (b,d),这将使它成为某种固定点。但是,如果这个类比成立,则let表达式必须以某种方式“搜索”d 的那个不动点(并且可能不止一个)。在我看来,这很接近魔术。还是我觉得太复杂了?

4

2 回答 2

14

这与作品的标准定义相同fix

fix f = let x = f x in x

即,它以完全相同的方式找到一个固定fix:递归。

例如,作为一个简单的例子,考虑loop (\((),xs) -> (xs, 1:xs)) (). 这就像fix (\xs -> 1:xs); 我们忽略我们的输入,并使用d输出(这里xs)作为我们的主要输出。元组中的额外元素loop只是包含输入参数和输出值,因为箭头不能进行柯里化。考虑一下如何定义阶乘函数fix——你最终会使用柯里化,但是当使用箭头时,你会使用额外的参数和输出loop给你。

基本上,loop打结,让箭头访问自身的辅助输出,就像fix打结一样,让函数访问自己的输出作为输入。

于 2012-03-24T23:30:15.767 回答
6

“搜索固定点”正是这样做的。这是 Haskell 在行动上的懒惰。在维基百科上查看更多信息。

于 2012-03-24T22:56:22.610 回答