谈到 let,我认为 letP = Q in R
会评估Q -> Q'
thenP
被替换为Q'
in R
,或者:R[P -> Q']
。
从道德上讲,是的,但P
不会立即评估,而是在需要时进行评估。
但是在修复定义中Q
取决于R
,那么如何评估呢?
Q
不依赖R
,依赖P
。这使得P
递归地依赖于自身。这可能导致几种不同的结果。粗略地说:
如果Q
在评估之前不能返回其结果的任何部分P
,则P
表示无限递归计算,它不会终止。例如,
let x = x + 1 in x -- loops forever with no result
-- (GHC is able to catch this specific case and raise an exception instead,
-- but it's an irrelevant detail)
如果Q
可以在需要评估之前返回其结果的一部分P
,它会这样做。
let x = 2 : x in x
-- x = 2 : .... can be generated immediately
-- This results in the infinite list 2:2:2:2:2:.....
let x = (32, 10 + fst x) in x
-- x = (32, ...) can be generated immediately
-- hence x = (32, 10 + fst (32, ...)) = (32, 10+32) = (32, 42)
我想这是关于惰性评估的。Q'
变成了重击,但我无法在脑海中推理。
P
与 thunk 相关联。重要的是这个 thunk 在返回输出的某些部分之前是否调用自己。
作为上下文,我正在查看 Y 组合器,它应该找到一个函数的固定点,所以如果我有这个函数。one x = 1
,那么fix one == 1
一定要持有,对吧?
是的。
所以fix one = let x = one x in x
,但我不明白为什么1
会从中出现
我们可以这样计算:
fix one
= {- definition of fix -}
let x = one x in x
= {- definition of x -}
let x = one x in one x
= {- definition of one -}
let x = one x in 1
= {- x is now irrelevant -}
1
只需扩展定义。保留递归定义,以防您再次需要它们。