Proposal: Not allow built-in types to be redefined

It is currently possible to redefine built-in types in Rescript, for example:

type string = int

It is fair to assume that there is no real use cases for such piece of code?
Why I am proposing this is that if keep such invariant, some code optimisations should be easy to do, see this: https://github.com/rescript-lang/rescript-compiler/issues/4930

It is easy to accomplish this by just doing a check during the parsing

10 Likes

Haha didn’t even know this was possible, what’s the use case?

I’ve been considering doing this myself, as an experiment, to change array to a custom immutable type. It’s just an idea at this stage, and probably a bad idea, so if it becomes impossible in the service of better JS output that seems fine.

1 Like

Not a ReScript project, and I’m not saying it’s a great name, but it is done sometimes: https://github.com/yawaramin/ocaml-decimal/blob/2907175c02ca1bb117ee9703b8d642b721a3d6e8/lib/decimal.ml#L3

For what its worth, I’m against this change. The ability to do the above can be used in the provision on a DSL. It’s also common to do this in JS for polyfills, and therefore not unorthodox for a JS audience to expect this kind of functionality as something useful.

Any practical advantage to call t instead of array?

While I don’t really like this restriction for the reasons others have mentioned, it’s worth saying that we can always use a slightly modified version of the type name, like array_. I would normally recommend this pattern anyway, to avoid confusion.

I am not sure how it is related. A concrete example would be useful

In my case we’re starting to use a custom ImmutableArray.t instead of array in a lot of places and it’s becoming quite inconvenient :slight_smile:

I did not get it. why is it inconvenient?

It’s visual noise when reading the code. We have wrapper functions for all the usual things we do with array so instead of Array.map we’re using ImmutableArray.map etc etc. The string ImmutableArray. now appears in our codebase 226 times.

We could rename the module to Array for convenience, which would also mean accessor syntax (value[i]) redirects to our immutable get implementation, but when type array is not the same as Array.t I think that will be extremely confusing.

Hmm, if you like short names, you can just do module I = ImmutableArray and have I.t everywhere which is even shorter than array…

I misread the post - I thought the proposal was to remove the ability to add aliases for built-in modules.

After actually reading through the Github issue and looking at the proposals, I think the correct tradeoff would be to go ahead with not allowing built-in types to be redefined as you suggested.

I apologize - I should have looked at the issue report first.

1 Like

The module is Signal, and it exposes the types id and array. The latter is to express the concept that it’s an array (mutable) of signal IDs. I thought about calling it set but having both a type set and a function set seemed too confusing.

I think Signal.t wouldn’t really express that this is an array of signals.

Another example: Problem with inferred type

I suspect that people coming from certain communities e.g. Rust, will tend to re-define result.

Short but meaningful is my mantra. I.t just feels like code golf.

As I said I haven’t actually tried to redefine array yet, I’m holding off on my experiment until a decision is made here.

You could add module Array = ImmutableArray to your project’s standard lib and open it everywhere. I think shadowing modules is still cleaner than redefining built-in types. You’d still have to use Array.t instead of array though.

One reason I find redefining array troublesome (besides liking Hongbo’s proposal in general) is interop: do you want to pass ImmutableArray.t to JS libraries? Depends on the t implementation, I guess, but even if it’s the same array under the hood, you lose immutability guarantees when you deal with JS. So maybe you still need a type for mutable arrays (unless you go the Elm way and abstain from using JS libraries).

EDIT: grammar

3 Likes

Hi all, the general guide line is that we should not redefine built-in types, since it is confusing to users and the benefit is not clear.

So what are built-in types? I think types which require special treatment in the compiler are considered built-in types. Here is a list of types I have in mind:

  • int
  • char
  • bytes
  • float
  • bool
  • unit
  • exn
  • array
  • list
  • option
  • int32
  • int64
  • lazy_t
  • string
6 Likes