Error compiling @rescript/core with Rescript 11

but it also has been updated to use @core 1.1.3 as npm shows, could be any type of dependency resolution error or some kind of dependency cache from npm?

I think I got the answer, not sure if interest you guys but I’ll leave here anyways in case someone has the same problem that I was having. I also created a minimal repro environment in this repo

The issue is:

Core__List module has a function defined reduceReverse:

let reduceReverse = (type a b, l: list<a>, acc: b, f) => {
  let len = length(l)
  if len < 1000 {
    reduceReverseUnsafe(l, acc, f)
  } else {
    A.reduceReverseU(toArray(l), acc, f)
  }
}

as you can see, the else branch does:

A.reduceReverseU(toArray(l), acc, f)

A is defined earlier as:

module A = {
  let makeUninitializedUnsafe = Belt_Array.makeUninitializedUnsafe
  let reduceReverseU = Belt_Array.reduceReverseU
  let reduceReverse2U = Belt_Array.reduceReverse2U
}

So in the end, we’re calling Belt_Array.reduceReverseU

Checking Belt_Array’s definition here we can see that it calls the function with the uncurry syntax explicitly: f(. r.contents, getUnsafe(a, i))

So, the whole issue is, if uncurried is set to false in rescript.json the compiler assumes that the function that the Core__List.reduceReverse is receiving as argument is curried, but Belt_Array only accepts uncurried functions, since it’s explicitly using the uncurried syntax to call it, so the compiler throws an error.

If you change uncurried to true in rescript.json, the exception goes away, because now the compiler assumes that the function passed to Core__List.reduceReverse is already uncurried and would have no issues when Belt__Array calls it with the uncurried syntax.

In summary, @rescript/core is not compatible with uncurried: false as long as we use Belt underneath.

I think this could be stated in a clearer way in the documentation.

CC: @fham @jihchi @tsnobip

1 Like

We just released 1.4.0 of Core that removes the internal dep on Belt. Could you try that?

3 Likes

Hey @zth thanks for the reply! I tested and it indeed seems to work, but it’s outputting another error now:

I’m not sure if uncurried changed something about optional parameters, but it seems not accepting the call that is done inside Core__Int.fromString where it calls the Core__Float.parseInt) without the radix.

Maybe we can benefit of the new syntax and instead of the switch we could do just Core__Float.parseInt(x, ~radix=?radix) or even Core__Float.parseInt(x, ~radix=radix) ?

@zth Actually, looking at the module itself and its interface, I can see that the function are defined equally in both:

here is @rescript/core/src/Core__Float.resi:

@val
external parseInt: ('a, ~radix: int=?) => float = "parseInt"

And here is @rescript/core/src/Core__Float.res

@val external parseInt: ('a, ~radix: int=?) => float = "parseInt"

From this part of the documentation, if the function type annotation has ~paramName: type=? the function implementation should have ~paramName: option<type> doesn’t it? Not sure how this works with the external keyword.

But besides that, I could see this:
image

We have a parseIntWithRadix that is deprecated and suggesting the usage of the parseInt with optional arguments, but isn’t this the exactly opposite what rescript recommends on the documentation?

Shouldn’t we “undeprecate” parseIntWithRadix and make parseInt receive only the integer and not an optional radix?

Core__Int.fromString could call Core__Float.parseInt(x) (which is per se a little odd to me, why the Int module would call the Float module to parse an Int value?) or Core__Float.parseIntWithRadix(x, ~radix)

Actually, newer versions won’t work anymore as stated in the Readme. The only way this could be fixed is to release a version 1.2.1 or something that gets only rid of the dependencies on Belt but does not introduce the new way of binding a function with trailing optional parameters instead of having multiple functions.

@zth not sure if we should go down that avenue, since uncurried will be the only mode in v12.

1 Like

I don’t mind doing a series of 1.2.x that continues to fix things for curried mode. Uncurried will be the default from v12 going forward, and that’s where we focus our efforts, but some are going to need to remain on curried for a while, so 1.2.x releases can help accomodate that.

3 Likes

this is indeed true for regular function implementations, but here we only define external bindings, there’s no function body so it doesn’t apply here.

1 Like

Ok, so if I understood correctly, the way to go is to adopt uncurried if I want to use @rescript/core

1 Like