Why this Haskell code never terminates?

后端 未结 2 591
粉色の甜心
粉色の甜心 2021-01-18 22:44

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

main :: I         


        
相关标签:
2条回答
  • 2021-01-18 23:24

    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)

    0 讨论(0)
  • 2021-01-18 23:39

    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.

    0 讨论(0)
提交回复
热议问题