OCaml-функторы, классы типа Haskell и множественный вывод

Хорошо известно, что OCaml имеет параметрический полиморфизм, и это приводит к некоторым ограничениям. Haskell через его классы типов предлагает специальный полиморфизм, который, очевидно, очень удобен в нескольких ситуациях. Также хорошо известно, что система модулей и функторов OCaml позволяет создать своего рода специальный полиморфизм. См. Замечательный недавний ответ Саймона Шина здесь, например.

Моя точка зрения заключается в том, что в Haskell можно создавать типы, которые выводят классы типов. Например:

data Person = Person { firstName :: String
                 , lastName :: String
                 , age :: Int
                 } deriving (Eq, Show, Read)

Это очень удобно для определения типов, имеющих несколько функций (позволяющих значения типа Person поддерживать тесты равенства, быть пригодными для печати и читаться в данном примере).

Мой вопрос заключается в следующем: можем ли мы сделать то же самое, просто в OCaml? Просто я имею в виду с основным синтаксисом языка и без многих уловок.

Чтобы привести несколько конкретный пример, предположим, что у нас есть две сигнатуры OCaml

module type Showable = sig
    type t
    val to_string : t -> string
end

module type Readable = sig
    type t
    val from_string : string -> t
end

Цель состоит в том, чтобы написать функтор F, параметризованный модулем, который реализует как Showable, так и Readable.

Ответ 1

Конечно, на самом деле это довольно простое использование модуля.

module type S = sig
  include Showable
  include Readable with type t := t (* destructive substitution *)
end

module F ( M : S ) = struct
  let fake_id x = M.from_string @@ M.to_string x
end

Деструктивная замена объясняется в руководстве: http://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec234
Остальное - обычный материал модуля (см. Руководство для полного объяснения)

Некоторые библиотеки, несущие функтор, очень много полагаются на такой структурный подтипинг. Например, каждый функтор в ocamlgraph определяет свой собственный аргумент типа модуля. Вот пример с модулем Kruskal. Функтор ожидает модуль типа Kruskal.G, который реализует подзадачу Sig.G (которая реализуется большинством модулей графа).