Как сделать полиморфные варианты Ocaml приватными

Я хотел бы переключить некоторые из моих типов на использование полиморфных вариантов Ocaml, учитывая их с открытой рекурсией, сохраняя при этом соблюдение моих существующих частных неполиморфных типов, а также проверку исчерпывающей информации о совпадениях с образцами.

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

Я должен добавить, что раньше использовал полиморфные варианты, но переключился на обычные, потому что вывод типов не очень хорошо работает с полиморфными вариантами: сообщения об ошибках трудно читать, и они ошибочны гораздо больше, чем обычные неправильные выводы, требующие много больше аннотаций типа на параметры, чтобы сохранить здравомыслие. Проблема в том, что без них принудительное применение частными конструкторами является сильным, а принудительное применение клиентских алгоритмов - слабым.

Я не совсем уверен, возможно ли или целесообразно ли объединять "специальные" подмножества конструкторов с конфиденциальностью. Любые предложения относительно того, насколько это практично?

РЕДАКТИРОВАТЬ: простые примеры типов:

(* open *)
type 'a x' = [`A | `B of 'a]

(* closed *)
type x = private 'u x' as 'u

(* open extension *)
type 'a y' = ['a x' | `C of 'a] 

(* closed extension *)
type y = private 'u y' as 'u 

let mkA () = `A
let mkB' (a:'a x') = `B a

(* how to do this? *)
let mkB (a:x) = mkB' (a :> 'a x')

При открытой рекурсии функции конструктора должны следовать шаблону открытых / закрытых типов. Клиент только увидит закрытые версии. Это означает, что в отличие от моей нынешней системы, где достаточно одной функции конструктора, мне теперь нужна одна для каждого закрытого типа, для каждого типа, в котором содержится конструктор.

Даже если я смогу понять, как это сделать, что довольно сложно, если вы скажете 6 взаимозависимых типов, ВСЕ из которых используют открытую рекурсию, что приводит к экспоненциальному взрыву возможных комбинаций, не ясно, является ли это преимуществом по сравнению с просто принимать проверки времени выполнения. У меня заняло около 2 часов, чтобы добавить новый конструктор, потому что каждое сопоставление с образцом терпит неудачу с ошибкой исчерпанности и должно быть исправлено... даже если новый конструктор не используется на этом этапе компиляции.'

1 ответ

Приватный полиморфный вариант интересен только с модулем и интерфейсами. Они довольно просты в модуле, но приватны снаружи благодаря интерфейсу. Если за пределами модуля вы хотите иметь доступ к общедоступному представительству, вам нужно предоставить функцию, которая сделает это:

module M : sig
  (* open *)
  type 'a x' = [`A | `B of 'a]
  (* closed *)
  type x = private 'u x' as 'u
  val f: x -> x x'
end = struct
  type 'a x' = [`A | `B of 'a]
  type x = 'u x' as 'u
  let f a = a
end

Еще один способ сделать это - немного изменить свой тип, сделав приватным только главный конструктор:

(* open *)
type 'a x' = [`A | `B of 'a]
(* closed *)
type x = 'u x' as 'u
(* private *)
type px = private x
let f (a: px) = (a :> x)
Другие вопросы по тегам