如何在包含模块之外匹配私有多态变体类型?

How to match private polymorphic variant type outside of containing module?

我可以使用 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

Error: Cannot create values of the private type 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
          ^^^^^^^^^^^^^

Error: This expression has type Polymorphic.t but an expression was expected of type [< `X | `Y ]

let x = match Polymorphic.x with
  | `X -> 1
  | `Y -> 2 
| `X -> 1
  ^^

Error: This pattern matches values of type [? `X ] but a pattern was expected which matches values of type Polymorphic.t

let x = match Polymorphic.x with
  | Polymorphic.`X -> 1
  | Polymorphic.`Y -> 2 
| Polymorphic.`X
              ^

Error: Syntax error

let x = 
  let open Polymorphic in
  match x with
  | `X -> 1
  | `Y -> 2
| `X -> 1
  ^^

Error: This pattern matches values of type [? `X ] but a pattern was expected which matches values of type Polymorphic.t

是否可以匹配声明容器外的私有多态变体类型?
如果是——怎么样?如果不是 - 为什么?

私有类型的本质是它们是可见类型的私有子类型。特别是私有类型的值可以用 :> 强制转换为可见类型。

所以,这对我有用:

# match (Polymorphic.x :> [`X|`Y]) with
  | `X -> 1
  | `Y -> 2
  ;;
- : int = 1

对于它的价值,我认为像 `X 这样的多态变体值是普遍存在的,例如数字 1234。所以 `X`Y 没有那么多定义在 Polymorphic 中引用。即,没有与不合格值 `X.

不同的特殊 Polymorphic.(`X)

但是有一个 type Polymorphic.t 是模块特有的。可以将此类型的值强制转换为 [ `X | `Y ],但反之则不行。

我希望我看待这个问题的方式不会太错误 :-) 我希望这对您有所帮助。