This is just a question to better understand how the type system works: no direct practical application I’m trying to achieve. Sorry if my syntax is out of date, I haven’t switched to ReScript yet.
If I wrap the following JS:
let logPlain2 = (a, b) => console.log(a, JSON.stringify(b));
like this, in Util.re:
[@bs.module "./jsScratch"] external logPlain2: ('a, 'b) => unit = "logPlain2";
Then I can use it like this (where doc is a non-string type:
Util.logPlain2("x", "y");
Util.logPlain2("doc x", doc);
I think it doesn’t matter here, but the type of doc is defined like this in another module – the point is, it’s not a string, unlike “y”:
type t('w) = 'w;
But if I instead do this:
let logPlain2: ('a, 'b) => unit = [%raw
{|(a, b) => console.log(a, JSON.stringify(b))|}
];
Then I can’t do this:
logPlain2("x", "y");
logPlain2("doc x", doc);
I gather this is related to weak polymorphism, which I only partially understand. I do see why it rejects the last bit of code there (at least once it has decided that the type variables are weakly polymorphic).
So two questions actually:
-
I assume that the version wrapped with
[%raw ...]
has a different type that the one wrapped with[@bs.module ...]
, but they appear to have the same type in their definitions. How do the types differ (I guess I should say type declarations rather than types perhaps)? Is the difference just that one isexternal
? -
Is it possible to write a function that behaves like the
[@bs.module ...]
-wrapped one when using[%raw]
?