【发布时间】:2018-02-02 06:47:39
【问题描述】:
我正在编写一个类似这样的函数:
f x = let
x = ...
in
e
由于 Haskell 中的作用域规则,任何在 e 中使用 x 都将解析为 let 构造中的 x 定义。
为什么在 Haskell 中允许这样的事情? 编译器不应该拒绝这样的程序,告诉我们不能绑定与函数参数同名的值。
(这个例子可能很简单,但在现实世界的上下文中,变量具有与之相关的语义意义,很容易犯这样的错误)
【问题讨论】:
-
名称/标识符/变量阴影在许多编程语言中通常是允许的。如果被禁止,
f x = x+1将停止工作,因为有人在某处添加了全局x=42,或者只是因为某些导入库的更新版本现在导出了x。即使在 lambda 演算中\x. \x. ...也是允许的(这稍微简化了语义)。 ML 甚至允许let x = x+1 in ...,这在 ML 中不是递归的,这已成为惯用的。现在,我并不是说阴影是好的,但 IMO 对此的编译器警告总比错误好。 -
在像 Haskell 这样高度递归的语言中,可能很难将变量名的意外重用与有意递归区分开来......
-
@MathematicalOrchid 确实如此。我刚刚修复了我的代码中的一个错误,该错误导致程序中出现无限循环。