Empty records and record types?

I am new to the language and attempting to model tables in OCaml. My current implementation (an object with 1 attr, a list of records) seems to meet my criteria but is not sufficient for reasoning about empty tables, as OCaml does not seem to let me define record types with no fields or just perform top level checks.

My table encoding

(* table *)
class type table_templ = object
  method columns: 'a list
  method add_rows: 'a list -> 'a list

class ['a] table  = object
  val mutable columns : 'a list = []
  method columns : 'a list = columns
  method add_rows : 'a list -> 'a list  = fun rows ->
    columns <- rows @ columns;

Working example

type student =
    name: string option;
    age: int option;
    favourite_color: string option;

let bob = {name = Some "Bob"; age = Some 12; favourite_color = Some "blue";}
let alice = {name = Some "Alice"; age = Some 17; favourite_color = Some "green";}
let eve = {name = Some "Eve"; age = Some 13; favourite_color = Some "red";}

let e = new table;;
e#add_rows [bob; alice; eve];;

Issue with empty tables

type empty = { };;
let empty_record_instance: empty = { };;

let empty_table = new table;;
empty_table#add_rows [empty_record_instance];;

I would appreciate any suggestions around making this approach work but I am also open to alternative ideas for encoding tables that already fit the language’s type system and my criteria.

You can use a single constructor instead :

type empty = Empty

and then

let empty_instance = Empty

Then it is not a record type, but it behaves exactly as an empty record would : you do not have subtyping for records.

You could also just use the type unit which is a predefined type with a single constructor (())

1 Like

I think I already tried that but was unable to extend the empty table with a new schema later on. Is this is even a behaviour I would be able to achieve if empty records were possible?

I am not sure what you mean by expanding the schema. Are you sure it is possible even with non-empty record ?

It sounds like something that would require subtyping, that is that if you have

type a = {x : float}
type b = {x: float; y: float}

then a value of type b can also be used as if it was a value of type a.

OCaml does not have for records because it has a performance cost, and you do not need it all the time. If you want that behavior you need to use objects, which I believe support empty objects:

let empty_object_instance = object end

(You also do not have to name object types)

1 Like

I think empty records would be a useful addition to the language, but there was quite a bit of discussion on the topic a few years ago:

which ended in adding support for empty variant types but not empty records.