Search code examples
haskelllet

Haskell: let statement, copy data type to itself with/without modification not working


I want to update a record syntax with a change in one field so i did something like:

let rec = rec{field = 1}

But I've noticed that i can't print rec anymore, means the compiler seems to get into an infinite loop when i try. so i have tried doing:

let a = 1 -- prints OK

let a = a -- now i can't print a (also stuck in a loop) 

So i can't do let a = a with any type, but i don't understand why, and how should i resolve this issue.

BTW: while doing:

let b = a {...record changes..}

let a = b

works, but seems redundant.


Solution

  • The issue you're running into is that all let and where bindings in Haskell are recursive by default. So when you write

    let rec = rec { ... }
    

    it tries to define a circular data type that will loop forever when you try to evaluate it (just like let a = a).

    There's no real way around this—it's a tradeoff in the language. It makes recursive functions (and even plain values) easier to write with less noise, but also means you can't easily redefine a a bunch of times in terms of itself.

    The only thing you can really do is give your values different names—rec and rec' would be a common way to do this.

    To be fair to Haskell, recursive functions and even recursive values come up quite often. Code like

    fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
    

    can be really nice once you get the hang of it, and not having to explicitly mark this definition as recursive (like you'd have to do in, say, OCaml) is a definite upside.