Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
let绑定中的声明顺序,Haskell与OCaml_Haskell_Ocaml - Fatal编程技术网

let绑定中的声明顺序,Haskell与OCaml

let绑定中的声明顺序,Haskell与OCaml,haskell,ocaml,Haskell,Ocaml,在Haskell中,let/where构造中的声明顺序并不重要,例如: f x = let g1 x y = if x>y then show x else g2 y x g2 p q = g1 q p in ... 其中,g2用于声明前的g1。 但在Ocaml中并非如此: # let a = b in let b = 5 in a;; Warning 26: unused variable b. Error: Unbound value b O

在Haskell中,let/where构造中的声明顺序并不重要,例如:

f x = let g1 x y = if x>y then show x else g2 y x
          g2 p q = g1 q p
      in ...
其中,
g2
用于声明前的
g1
。 但在Ocaml中并非如此:

# let a = b in
  let b = 5 in
  a;;
Warning 26: unused variable b.
Error: Unbound value b
OCaml行为不像Haskell有什么原因吗?在没有转发声明的情况下,此功能对我来说似乎很有用


这是因为OCaml中的严格评估而Haskell中的懒惰吗?

不是严格本身,但这是同一问题的症状


Ocaml不是纯功能性的,也就是说,任意函数调用可以执行任意I/O。这要求它们以可预测的顺序运行,这需要严格性和您注意到的let顺序。

在Haskell中,这不是因为懒惰的计算。弄清楚哪个名称指的是编译时发生的事情,而实际上什么都没有执行(严格地或惰性地)。请记住,在Haskell中,您只编写数学定义,而不是按顺序执行的命令。以什么顺序编写这些定义并不重要。不管你说

a = expr1
b = expr2

这意味着
a
被定义为
expr1
b
被定义为
expr2


我不知道任何OCaml,所以对此我不能说什么。

OCaml使用“let rec”来指示组中的绑定何时可以相互引用。没有额外的“rec”,绑定必须是自上而下的顺序。有关详细信息,请参见中的“本地定义”。

Haskell消除了古老的
let
let rec
的区别。 一个好的编译器可以很好地理解它是一个简单的let,还是一个包含相互递归定义的let,并且可以相应地执行操作


(我想知道如果一个ML编译器从
let-rec
开始,然后只有非递归定义,它会做什么。当然,当一个人进行重构时,let/let-rec这件事是一个严重的障碍。)

注意在Haskell中,直接翻译
let a=b in let b=5 in a
仍然是非法的。不过,我很想做
let x=x+1
。你可以在任何地方写
let rec
。编译器不会抱怨的。
let
的好处是允许您确保所定义的内容不会导致意外循环,例如:
let x=x+1
,正如missingo所建议的那样。有时,人们喜欢能够在范围内定义一个新变量,并将现有变量隐藏在范围外,设置为旧变量的某种转换。自动
let rec
会阻止这种情况发生。@JonHarrop什么不正确?Haskell解决了这个问题?我发现当我更新“状态”变量时,阴影变量有时很有用,因为这样做可以防止我意外误用旧版本。我同意lambda黑客确实非常丑陋——我只是指出了一种在Haskell中实现非letrec“let”的方法。我几乎无法想象一个更不准确、更偏颇、更离题的答案。OP在此询问范围界定规则,这是一个独立于任何评估顺序考虑的主题。此外,即使在纯惰性语言中,也有充分的理由限制同时绑定作用域,例如,如果您想允许对以前定义的标识符进行隐藏。
b = expr2
a = expr1