← Back to context

Comment by creata

1 day ago

Haskell can have circular references because its laziness is implemented with thunks, which have a mutable cell in which to store the computed value so that terms don't get evaluated more than once. Here's a Haskell function that makes a circular linked list:

    -- circular linked list with one item
    repeat x = let xs = x:xs in xs

Here's a rough equivalent in JavaScript that doesn't use thunks, just functions:

    function repeat(x) {
        function xs() {
            return [x, xs]; // [first, rest]
        }
        return xs;
    }

The Haskell version has a cycle because, after evaluation, `repeat x` will be a circular linked list, but all the "lists" we create in the JavaScript code above are just the closure `xs`.

For completeness, here's a JavaScript version that uses thunks:

    class Thunk {
        constructor(f) { this.f = f; }
        get() { if (this.f) { this.v = (this.f)(); delete this.f; } return this.v; }
    }

    function repeat(x) {
        let xs = new Thunk(() => {
            return [x, xs]; // [first, rest]
        });
        return xs;
    }

If you try calling `x = repeat(1); x.get()`, you can see that we get a circular list.