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
.
https://github.com/roc-lang/roc/issues/6485
Thinking I might have run into this!
Compiler stack overflow or execution stack overflow?
Nothing exists for this, at least not currently
Parser is in rust currently. No plans for roc parsing in roc cureently
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.
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 *
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 *
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)
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)
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
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