1

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

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 类型的值匹配

是否可以在声明容器之外匹配私有多态变体类型?
如果是 - 如何?如果不是 - 为什么?

4

1 回答 1

2

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

所以,这对我有用:

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

对于它的价值,我认为多态变量值`X很普遍,比如数字 1234。所以`X`Y没有Polymorphic像那里引用的那样定义太多。即,没有Polymorphic.(`X)与 unqualified value 不同的特殊值`X

但是有一种特定于模块的类型。 Polymorphic.t这种类型的值可以被强制,[ `X | `Y ]但不能反过来。

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

于 2020-07-17T18:49:20.607 回答