OCaml allows to mark type as private in the signature. And it makes sense. The object of type declared as private can be created only inside the module and be read outside.
module X : sig
type t = private { value : int }
val make : int -> t
end = struct
type t = { value : int }
let make x = { value = x }
end
let x = X.make 3 (* OK *)
let value = x.value (* OK *)
let x = X.{ value = 3 } (* ERROR *)
It is clear. But OCaml also provides the ability to declare private type inside the module structure.
module X : sig
type t = private { value : int }
val make : int -> t
end = struct
type t = private { value : int }
let make x = { value = x } (* ERROR *)
end
Error: Cannot create values of the private type t
It looks like a stupid feature because nobody needs a type when it is impossible to create any object of it.
For me looks more logical when private is an attribute that is allowed only in the signature level like abstract type.
What does OCaml have a private type in the struct for?
For the same reason that you can declare fully abstract types: values of those types can be created by external functions, for instance
type t = private int
external f: unit -> t = "some_c_function"
Moreover, this makes type definitions more regular since the same type definition is always allowed in both signatures and structures.