问题描述
最近我写了一些Haskell代码,它永远不会终止。在仔细检查我的代码后,问题归结为以下代码块: main :: IO()
main = print $ let a = 10 in
let a = a in
a :: Int
我想这与Haskell的懒惰有关,因为相同的代码在OCaml中终止。但是,如果我写了下面的代码而不是
main :: IO()
main = print $ let a = 10 in
let b = a in
b :: Int
根本没有问题。由于在原始代码中我不能理解这个原因,所以这两个a应该被认为是两个不同的变量。我不知道为什么它们的命名与程序的语义有什么关系。
问题是, ,与OCaml不同,Haskell中的 let
绑定默认为递归。所以 let x = x in ...
相当于OCaml的 let rec x = x in ...
一个循环定义。
这就是为什么在Haskell中映射变量名称(即多次定义 这个默认值在Haskell中比OCaml更有意义,因为懒惰,循环值(而不仅仅是递归函数)实际上是有用的。 I recently wrote some Haskell code and it never terminates. After I carefully examined my code, the problem boiled down to the following code piece I guess this must have something to do with the laziness of Haskell since the same code terminates in OCaml. However, if I wrote the following code instead the code would have no problem terminating at all. I can't get the reason since in the original code, the two a's should be considered as two different variables. I don't know why the naming of them has anything to do with the semantic of the program. The issue is that, unlike OCaml, This is why shadowing variable names in Haskell (ie defining This default makes more sense in Haskell than OCaml because, thanks to laziness, circular values (rather than just recursive functions) are actually useful. At the same time, some people don't like this for basically exactly the reason you ran into here: it's possible to introduce unintuitive infinite loops in your code, which makes some errors and typos harder to track down. This is also confusing because, by necessity, 这篇关于为什么这个Haskell代码永远不会终止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! a
)被认为是不好的原因风格,甚至有一个编译器警告,您可以打开 -Wall
标志或更具体地 -fwarn-name-shadowing $ c
let x = 1:x
给了我们无限的 1
列表,我们可以像普通列表一样使用它。与此同时,有些人并不喜欢这一点,基本上就是你碰到这里的原因:可能会在你的代码中引入不直观的无限循环,这使得一些错误和拼写错误难以追查。这也令人困惑,因为必要时,默认情况下,do_meation 中的< -
绑定不是递归的,这有点不一致。 main :: IO ()
main = print $ let a = 10 in
let a = a in
a :: Int
main :: IO ()
main = print $ let a = 10 in
let b = a in
b :: Int
let
bindings in Haskell are recursive by default. So let x = x in ...
is equivalent to OCaml's let rec x = x in ...
and is a circular definition.a
multiple times) is considered bad style and even has a compiler warning, which you can turn on with the -Wall
flag or more specifically -fwarn-name-shadowing
.let x = 1:x
gives us an infinite list of 1
, which we can use just like a normal list.<-
bindings in do-notation are not recursive by default, which is a bit inconsistent.