Why this Haskell code never terminates?

僤鯓⒐⒋嵵緔 提交于 2019-12-01 18:13:15

The issue is that, unlike OCaml, 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.

This is why shadowing variable names in Haskell (ie defining 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.

This default makes more sense in Haskell than OCaml because, thanks to laziness, circular values (rather than just recursive functions) are actually useful. let x = 1:x gives us an infinite list of 1, which we can use just like a normal list.

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, <- bindings in do-notation are not recursive by default, which is a bit inconsistent.

The second binding (a = a) shadows the other one. The first example is (almost) exactly equivalent to

main = print $ let xyz = 10 in
               let a = a in
               a :: Int

and I hope it's clear why that one doesn't terminate! You can get GHC to warn you about this by using the -fwarn-name-shadowing flag (or by entering :set -fwarn-name-shadowing in GHCi)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!