Как сопоставить частный полиморфный вариантный тип вне содержащего модуля?
Я могу закрыть возможность создания экземпляра вариантного типа вне содержащего модуля с помощью private
ключевое слово.
module Ordinary : sig
type t = private X | Y
val x : t
end = struct
type t = X | Y
let x = X
end
Я не могу создавать экземпляры Ordinary.t
и следующий пример не компилируется:
let f x = if x = Ordinary.X then 1 else 2
Ошибка: не удается создать значения частного типа Ordinary.t
Но я могу соответствовать Ordinary.t
и следующая функция работает нормально:
let f a = function
| Ordinary.X -> 1
| Ordinary.Y -> 2
Для меня это логически правильно, и я ожидаю такого же поведения от полиморфных вариантов. Аналогичный модуль я создал и для этого случая.
module Polymorphic : sig
type t = private [`X | `Y]
val x : t
end = struct
type t = [`X | `Y]
let x = `X
end
Но я не могу соответствовать Polymorphic.t
. Все мои попытки с сообщениями об ошибках показаны ниже:
let g a =
match a with
| `X -> 1
| `Y -> 2
let x = g Polymorphic.x
let x = g Polymorphic.x ^^^^^^^^^^^^^
Ошибка: это выражение имеет тип Polymorphic.t, но ожидалось выражение типа [<`X | `Y]
let x = match Polymorphic.x with
| `X -> 1
| `Y -> 2
| `X -> 1 ^^
Ошибка: этот шаблон соответствует значениям типа [? `X ], но ожидался шаблон, который соответствует значениям типа Polymorphic.t
let x = match Polymorphic.x with
| Polymorphic.`X -> 1
| Polymorphic.`Y -> 2
| Polymorphic.`X ^
Ошибка: синтаксическая ошибка
let x =
let open Polymorphic in
match x with
| `X -> 1
| `Y -> 2
| `X -> 1 ^^
Ошибка: этот шаблон соответствует значениям типа [? `X ], но ожидался шаблон, который соответствует значениям типа Polymorphic.t
Можно ли сопоставить частный полиморфный вариантный тип вне контейнера объявлений?
Если это так - как? Если нет - почему?
1 ответ
Суть частных типов в том, что они являются частными подтипами видимого типа. В частности, значения частного типа могут быть приведены с помощью:>
к видимому типу.
Итак, это работает для меня:
# match (Polymorphic.x :> [`X|`Y]) with
| `X -> 1
| `Y -> 2
;;
- : int = 1
Как бы то ни было, я думаю о значении полиморфного варианта, например `X
быть распространенным, как число 1234. Итак `X
а также `Y
не так сильно определены в Polymorphic
как указано там. Т.е. нет особенногоPolymorphic.(`X)
значение, отличное от неквалифицированного значения `X
.
Но есть тип Polymorphic.t
это относится к модулю. Значения этого типа можно принуждать к[ `X | `Y ]
но не наоборот.
Я надеюсь, что мой взгляд на это не слишком ошибочен:-) И я надеюсь, что это полезно.