ArrowLoop.loop的定义如何工作?

时间:2012-03-24 22:48:46

标签: haskell arrows

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的固定点(并且可能有多个)。这对我来说看起来很神奇。或者我觉得太复杂了?

2 个答案:

答案 0 :(得分:14)

这与fix的标准定义的工作方式相同:

fix f = let x = f x in x

,即它在exact same way fix does中找到了一个固定点:递归。

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

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

答案 1 :(得分:6)

“搜索固定点”完全这是做什么的。这是Haskell在行动中的懒惰。请参阅Wikipedia