'let rec' limitation? parser combinator

trying to write a Parser Combinator in ReScript (for fun, and Advent of Code).
Getting into problems with certain recursion, tho.

Plain oneOf(exact"hello"), exact("world")) works fine, both parsers produce the same type, but for a recursive type, I run into problems:

type rec expr =
  | Int(int)
  | Sub(expr)

let rec exprExpr = oneOf(intExpr, subExpr)
and intExpr = ...
and subExpr = ...  // needs to call exprExpr

The compiler tells me:
87 │ let rec exprExpr = oneOf(intExpr, subExpr)
This kind of expression is not allowed as right-hand side of 'let rec'
I’m not even sure what that means…
The types seem fine - with all kinds of variations I can get partial results.
What is the compiler complaining about (and what can I do to avoid that problem)?

Can you create a minimal reproduction? Maybe post it on the playground?

OCaml - Language extensions has some details on the limitations of recursive values. I ran into the same error recently and adding a parameter to the function fixed the error for me.

Here’s an example of mutually recursive functions that may help: https://rescript-lang.org/try?code=DYUwLgBAlhC8ECcQDMAUBGAlAKG6SSAxhMgPalwSqZwB8EA3thNMlVAHSGkB2YIfAM4R6AVhpMWLTtz4Cwg5hAC+EEMEEhGS6V178hlGfvnCA1BHQBuHdD1zDAKggAjAIYJqS5dh9ueACauHpTUdNrSbKjGDgoiEOIRUjEGCt5qGlqSyfapwvApphAW1raFTiTkXiw+PkA

The minimal case (thx tom) appears to be

let rec subExpr: unit => unit = () => finalExpr()

and finalExpr = subExpr

whereas

let rec subExpr: unit => unit = () => subExpr()

let finalExpr = subExpr

compiles fine. In terms of the OCaml ref (thx Kevin), the former case would be “immediately linked” in the recursive definition (I think). In the second case, there’s no recursion, so no problem. Unexpected, but there it is.

I believe the solution to my original problem lies in the direction of

let rec subExpr: unit => unit = () => finalExpr()

and finalExpr = () => subExpr()

(that can probably massaged into something better than using exprExpr() instead of exprExpr in various places)

2 Likes