Another advantage of naming the type t
inside of a record Person
is that the field names are qualified by the module and thus you can avoid conflict between same-named field of different types.
Taking your example from Are OCaml records structurally typed or nominally typed? can show how the fields of a newly defined type shadow the previous.
type student_t = { age: int }
let grade_level s = s.age - 5
type worker_t = { age: int }
(* even though we named the value student_a it has type worker_t because worker_t's definition for the age field shadows, or hides, the field from student_t *)
let student_a = { age = 14 }
(* so this code doesn't type check because student_a does not match the grade_level argument type *)
Printf.printf "grade level for student_a is %d\n" (grade_level student_a)
By defining types within modules, it is easy to specify which type of value we are creating:
module Student = struct
type t = { age: int }
let grade_level s = s.age - 5
end
module Worker = struct
type t = { age: int }
end
(* The Student. notation within the record specifies which module will be searched for the field names, ultimately determining the type of the value that is built. This results in student_a having type Student.t *)
let student_a = { Student. age = 14 }
(* and now this code will type check because student_a type matches the function argument type *)
Printf.printf "grade level for student_a is %d\n" (Student.grade_level student_a)