Stream: beginners

Topic: Weird stack overflow


view this post on Zulip Barend Venter (May 18 2024 at 11:29):

Was trying some basic church numeral stuff and when doing exponentiation ran into this example that overflows the stack: ((((\f -> \x -> f (f x))(\f -> \x -> f (f x))))(\x -> x + 1))(0)

This is surprising to me, is there something special I need to do in Roc for this to work? GHCi returns 4.

view this post on Zulip Barend Venter (May 18 2024 at 16:07):

https://github.com/roc-lang/roc/issues/6485

Thinking I might have run into this!

view this post on Zulip Brendan Hansknecht (May 18 2024 at 16:38):

Compiler stack overflow or execution stack overflow?

view this post on Zulip Brendan Hansknecht (May 18 2024 at 16:39):

Nothing exists for this, at least not currently

view this post on Zulip Brendan Hansknecht (May 18 2024 at 16:39):

Parser is in rust currently. No plans for roc parsing in roc cureently

view this post on Zulip Barend Venter (May 18 2024 at 16:40):

Given that I can wrap it in a function and it still crashed the REPL, I'm pretty confident now that it's some static analysis in the compiler. After all you can write neverEvaluated = \_ -> crash "Oh no!" without consequences, although I suppose the platform gets to choose how to handle crash and it's possible that the REPL handles it in some trivial way.

view this post on Zulip Krzysztof Kielak (May 19 2024 at 17:37):

Interestingly this works:

» f1 = ((\f -> \x -> f (f x)) \f -> \x -> f (f x))

<function> : (a -> a) -> (a -> a)
» f2 = f1 (\x -> x + 1)

<function> : Num a -> Num a
» f2 0

4 : Num *

view this post on Zulip Krzysztof Kielak (May 19 2024 at 17:45):

and even this:

» ff = ((\f -> \x -> f (f x)) \f -> \x -> f (f x)) (\x -> x + 1)

<function> : Num a -> Num a
» ff 0

4 : Num *

view this post on Zulip Krzysztof Kielak (May 19 2024 at 17:50):

It might be useful to note that this definition breaks - so there might be some scoping problem ... just guessing

» f = ((\f -> \x -> f (f x)) \f -> \x -> f (f x)) (\x -> x + 1)

── DUPLICATE NAME ──────────────────────────────────────────────────────────────

The f name is first defined here:

4│      f = ((\f -> \x -> f (f x)) \f -> \x -> f (f x)) (\x -> x + 1)
        ^

But then it's defined a second time here:

4│      f = ((\f -> \x -> f (f x)) \f -> \x -> f (f x)) (\x -> x + 1)
                                    ^

Since these variables have the same name, it's easy to use the wrong
one by accident. Give one of them a new name.



── DUPLICATE NAME ──────────────────────────────────────────────────────────────

The f name is first defined here:

4│      f = ((\f -> \x -> f (f x)) \f -> \x -> f (f x)) (\x -> x + 1)
        ^

But then it's defined a second time here:

4│      f = ((\f -> \x -> f (f x)) \f -> \x -> f (f x)) (\x -> x + 1)
               ^

Since these variables have the same name, it's easy to use the wrong
one by accident. Give one of them a new name.



── TYPE MISMATCH ───────────────────────────────────────────────────────────────

This expression is used in an unexpected way:

4│      f = ((\f -> \x -> f (f x)) \f -> \x -> f (f x)) (\x -> x + 1)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

It is:

    Num * -> Num *

But you are trying to use it as:

    (Num a -> Num a) -> (Num a -> Num a)

view this post on Zulip Barend Venter (May 19 2024 at 19:54):

Experimenting with the Y combinator, I notice something very confusing. If I shadow the name, it works, and correctly shows me a type error!

» y = (\x -> x x)(\y -> y y)

── DUPLICATE NAME ──────────────────────────────────────────────────────────────

The y name is first defined here:

4│      y = (\x -> x x)(\y -> y y)
        ^

But then it's defined a second time here:

4│      y = (\x -> x x)(\y -> y y)
                         ^

Since these variables have the same name, it's easy to use the wrong
one by accident. Give one of them a new name.



── CIRCULAR TYPE ───────────────────────────────────────────────────────────────

I'm inferring a weird self-referential type for y:

4│      y = (\x -> x x)(\y -> y y)
        ^

Here is my best effort at writing down the type. You will see ∞ for
parts of the type that repeat something already printed out
infinitely.

    ∞ -> ∞

But if I get rid of the name shadowing and call it something else, Roc breaks!

» fix = (\x -> x x)(\y -> y y)

thread 'main' has overflowed its stack
fatal runtime error: stack overflow
fish: Job 1, 'nix run github:roc-lang/roc -- …' terminated by signal SIGABRT (Abort)

view this post on Zulip Brendan Hansknecht (May 20 2024 at 00:07):

That's not too surprising. The first case just hits an error at an earlier stage in the compiler. So you get a pretty print out. The second example crashes the compiler later

view this post on Zulip Brendan Hansknecht (May 20 2024 at 00:07):

I assume it is crashing in type checking, but would need to see the exact stack trace


Last updated: Jul 05 2025 at 12:14 UTC