Тип — модуль
Для OCaml хорошей практикой является оборачиванием типа в модуль с определениям типа и функциями по его созданию, обработки.
Так как модули является не только средством пространства имён, но и средством инкапсуляции посредством сигнатур.
Общая практика состоит в том, что мы называем модуль названием типа, а внутри модуля определяем тип с именем t
(сокращение от type соответственно). Следование этому соглашению обеспечивает совместимость при работе с функторами и всем таким.
Если в одном модуле всё таки присутствует несколько определений типов, то к функциям по работе с ними добавляются суффиксы с названием типа (как в первом "плохом" примере).
Требования по знаниям
- Language documentation: Modules
Пример
Плохо
ocaml
(* lib.ml *)
type user = { name: string; age: int }
let make_user ~name ~age =
assert (age > 0);
{ name; age }
let pp_user fmt { name; age } =
Format.fprintf fmt "User('%s', %d)" name age
Лучше
ocaml
(* user.ml *)
type t = { name: string; age: int }
let make ~name ~age =
assert (age > 0);
{ name; age }
let pp fmt { name; age } =
Format.fprintf fmt "User('%s', %d)" name age
ocaml
(* user.mli *)
type t = private { name : string; age : int; }
val make : name:string -> age:int -> t
val pp : Format.formatter -> t -> unit
Смотрите также
- Сигнатуры модулей — описание возможностей сигнатур;
- Private types — пояснение про ключевое слово
private
;
В функторах
Пример c модулем Map
ocaml
module IntMap = Map.Make (Int)
Глупый пример из пальца:
ocaml
(* list.ml *)
module Make (Item : sig type t end) = struct
type t = Item.t list
end
ocaml
module Users = List.Make (User)