Generic function called with different types

I’m trying to create a function that depending on input types returns different output types using type params. But I’m not getting it to work, take a look at this playground:

https://rescript-lang.org/try?code=C4TwDgpgBAThDOYD2A7eEA8ByAhgGiiwCMA+KAXigCEIAbYAOgCUEBXeh4bfQ0gKChQ+fUJFgQAjqwRdcBYmUoBvAVFYxaALijxgMAJYoA5nlUATCAGMkFmNoAUASgpk4iVOm7z+AX2F9aCGBxKRkAQQooFUF1LSgAIgB6ADMkJHjTQQtrWwdncjIaDhZ4dkYAeQBrewAmRz4-AKCQ6V0qSOi1DW0kohwYDPMrGwg7KCcXajpGErKGKvt4gAk6WnT6xtFoHDB9AEk0YBwUS0w5XkUo8yRtOFDdLwvJt2Q0M54FBtVhQODWdDCAAU9pEJgUrlkbi0ZJNOoI7q1GNkRjAnKo-I17GCyJ1flAdvpIv8IEC9mjBASGGYkPYEeFHABaEj6IwoJBwVSU6m0ySIqiM5ms9kQBqOJxMllsjlAA

So it seems like the type parameter is “decided” on the first call do api.do, so all subsequent usage of the function is no longer generic. I guess this is just how it works. But is there another way to achieve this, without creating two variables (as seen on row 37)?

1 Like

Indeed, this is a limitation with the normal rules of polymorphism in ReScript. 'a gets unified with int, so then it cannot be unified with string.

There is a way around it, though. Instead of making 'a a type parameter of apiInstance, you need to annotate the do record field with an “explicit universally quantified” type annotation.

type apiInstance<'b> = {do: 'a. request<'a, 'b> => response<'a, 'b>}
//                     This ^^^

Playground link.

I’m not sure if this feature is documented in ReScript yet, but it’s an OCaml feature that ReScript inherited.

8 Likes

Worked great! Thank you so much, didn’t know there was OCaml features inherited even. Need to look into this more.

1 Like

Here is a nice blog post that introduces explicitly-polymorphic types in a simple way: https://www.craigfe.io/posts/polymorphic-type-constraints. It is about OCaml, but like johnj mentioned it works the same. Maybe it will help you out!

4 Likes