Search code examples
listhaskellrecursionfreeze

Haskell: Why is it a problem to re-assign the tail of a variable to its own variable?


Suppose you have a variable with the following list:

Prelude> arr = [1,2,3,4,5]

And you do,

Prelude> arr
[1,2,3,4,5]
Prelude> arr = tail arr
Prelude> arr

Why does the compiler freeze up now? I am trying to implement this code statement in a recursion, but this phenomenon is preventing my recursion from working properly – it keeps returning an empty list error.


Solution

  • In Haskell, a variable is always in scope in its own definition. What you probably intended was this

    Prelude> arr1 = [1,2,3,4,5]
    Prelude> arr1
    [1,2,3,4,5]
    Prelude> arr2 = tail arr1
    Prelude> arr2
    [2, 3, 4, 5]
    

    But when you write arr = tail arr, the REPL forgets the previous definition of arr and defines a new one which is equal to its own tail. Then you do

    Prelude> arr
    

    Haskell comes along and evaluates that to tail arr, and tail evaluates its argument to WHNF, so to identify tail arr, we need to know the shape of arr, which is, of course, tail arr. So to know arr, we need to know arr. Hence, arr is bottom, a nonterminating value. The previous definition is irrelevant.

    If you had tried to do this in a Haskell source file (as opposed to the command line interactive environment), you'd get a compiler error, as it's incorrect to rebind an existing name in the same scope. It's only a feature of the REPL that you're allowed to do so for testing purposes.