【问题标题】:Why this OCaml patterning matching doesn't compile?为什么这个 OCaml 模式匹配不能编译?
【发布时间】:2015-07-06 15:28:10
【问题描述】:

我有一个模块接口

module type Enum = sig
type t
val toInt : t -> int
val fromInt : int -> t
end

然后我有一个模块

module Navigability : Enum = struct
type t=
AB
| BA
| Both
| None

let toInt = function
| BA   -> -65536
| Both -> -1
| None -> 0
| AB   -> 65535

let fromInt = function
| -65536 -> BA  
| -1     -> Both
| 0      -> None
| 65535  -> AB  
| _ -> None

end

添加以下函数后,代码无法编译:

let fun = function
| Navigability.t.BA   -> false
| Navigability.t.Both -> true
| Navigability.t.None -> false
| Navigability.t.AB   -> true 

如果我把它放在模块内并取消接口,它就可以工作。

谁能告诉我为什么以及如何?

【问题讨论】:

  • 附带说明,fun 是 OCaml 关键字,不应用作函数名。
  • @PatJ 啊,我在这里发帖的时候把名字改成了fun 谢谢

标签: pattern-matching ocaml


【解决方案1】:

当您编写Navigability: Enum 时,您是在“密封”模块,使其接口仅限于Enum 中的内容。 BA 等值不在其中。

【讨论】:

    【解决方案2】:

    module type 是对绑定到它的模块外部可见内容的严格规范。因此,正如 Jeffrey Scofield 在他的回答中所说,键入 module Navigability : Enum 可确保在 Navigability 之外已知的唯一内容将是在 Enum 中定义的内容,并且您的类型构造函数不属于其中。

    确保类型可见性的一种简单方法是在模块外部声明它,然后用with 子句绑定它:

    type nav =
    AB
    | BA
    | Both
    | None
    
    module Navigability : Enum with type t = nav = struct
    
    type t = nav
    
    (* put other definitions here *)
    
    end
    
    let f = function
    | BA   -> false
    | Both -> true
    | None -> false
    | AB   -> true
    

    附带说明,您的构造 Navigability.t.AB 不正确,它应该只是 Navigability.AB。此外,fun 不能用作函数或变量名,因为它是关键字。

    如果您希望您的导航类型只能通过Navigability 访问,您可以保留您的定义,同时删除Enum 约束。无论如何,没有什么能阻止您以后将Navigability 用作Enum

    【讨论】: