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
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.