Why isn't the declaration of OCaml's record type a synonym?

81 views Asked by At

https://cs3110.github.io/textbook/chapters/data/type_synonym.html

As we can see above,

type a = int * int * int

type a is a synonym for int * int * int.

So, if we declare int * int * int by multiple names, they are all same type.

type a = int * int * int
type b = int * int * int
type c = int * int * int

a and b and c are the same types.

They do not have a data constructor. Indeed, need not, and should not because they are just a synonym.

However, when we look at records, it's quite different.

type a = { name : string }
type b = { name : string }
type c = { name : string }

a and b and c are different types. We can prove it by the code below.

({ name = "something" } : a) = ({ name = "something" } : b) ;;

// This expression has type b but an expression was expected of type a

It acts like "newtype" in Haskell, without a use of data constructor.

I heard that in OCaml, records are a primitive notion and they have their own identity. (You can see it from the url below.)

No type constructor for record types?

If then, why tuples and records act differently??

It makes me confuse.

I learned that the problem of duplicating the format of records can be solved by using a module. So this kind of confusion is not a big deal.

But I want to know why there is an inconsistency between tuples and records.

1

There are 1 answers

0
Andreas Rossberg On

The main reason is type inference. When you write a function

let f x = x.a

then the type system would not be able to tell the type of f if it could be any record type with a field a.

There are ways around the ambiguity, namely row polymorphism, which is what OCaml uses for the inference of object types:

let f o = o#a  (* infers type f : < a : 'a; .. > -> 'a *)

Here, <a : t; ..> means any object type with a field a of type t. However, the drawback is that this flexibility requires a more heavyweight and costly runtime representation for objects.

That said, Standard ML, which is OCaml's sister language, does indeed make records and tuples the same thing (literally, a * b * c is just a shorthand for {1 : a, 2 : b, 3 : c} in SML), but then requires the programmer to insert type annotations to resolve possible ambiguities, like in the example above.