为什么MCHaskell函数会导致栈溢出
Why does MC Haskell function result in stack overflow
我正在学习 Haskell 这本书的第 8 章。在做练习时,我注意到一些我不明白的地方。
为什么会导致堆栈溢出
mc x | x>100 = x-10
| otherwise = mc $ mc x+11
但这不是
mc x | x>100 = x-10
| otherwise = mc $ mc (x+11)
我认为这与 x+11 在第一个示例中未被计算有关,但不是总是计算这样的表达式
例如
Prelude> id 43+94
137
第一个表达式
mc $ mc x+11
被解释为
mc ((mc x) + 11)
因为函数应用优先于运算符。
第二个表达式
mc $ mc (x+11)
解释为:
mc (mc (x+11))
第一个确实永远不会被评估,因为如果你写:
<b>mc x</b> | x > 100 = x-10
| otherwise = mc (<b>(mc x)</b> + 11)
然后你根据mc x
定义mc x
。除非该表达式中的 mc x
未被计算,因此您将在计算 mc x
时调用 mc x
,因此它将继续调用。
这纯粹是关于运算符优先级的。特别是,函数应用程序优先于所有运算符。所以这个:
mc x+11
实际解析为
(mc x)+11
以及您尝试 "visually" 指示所需分组的间距或缺少间距的事实没有任何区别。这当然是你的第二个版本效果更好的原因,因为你明确指出了你想要的分组。
当然,无意的解释意味着,对于 x <= 100
,为了计算 mc x
,编译器必须首先计算 mc x
,依此类推。因此最终的堆栈溢出。
我正在学习 Haskell 这本书的第 8 章。在做练习时,我注意到一些我不明白的地方。
为什么会导致堆栈溢出
mc x | x>100 = x-10
| otherwise = mc $ mc x+11
但这不是
mc x | x>100 = x-10
| otherwise = mc $ mc (x+11)
我认为这与 x+11 在第一个示例中未被计算有关,但不是总是计算这样的表达式
例如
Prelude> id 43+94
137
第一个表达式
mc $ mc x+11
被解释为
mc ((mc x) + 11)
因为函数应用优先于运算符。
第二个表达式
mc $ mc (x+11)
解释为:
mc (mc (x+11))
第一个确实永远不会被评估,因为如果你写:
<b>mc x</b> | x > 100 = x-10
| otherwise = mc (<b>(mc x)</b> + 11)
然后你根据mc x
定义mc x
。除非该表达式中的 mc x
未被计算,因此您将在计算 mc x
时调用 mc x
,因此它将继续调用。
这纯粹是关于运算符优先级的。特别是,函数应用程序优先于所有运算符。所以这个:
mc x+11
实际解析为
(mc x)+11
以及您尝试 "visually" 指示所需分组的间距或缺少间距的事实没有任何区别。这当然是你的第二个版本效果更好的原因,因为你明确指出了你想要的分组。
当然,无意的解释意味着,对于 x <= 100
,为了计算 mc x
,编译器必须首先计算 mc x
,依此类推。因此最终的堆栈溢出。