Ocaml 包含函子应用程序的子模块

Ocaml 包含函子应用程序的子模块,ocaml,Ocaml,我有一个函子,它有一个子模块: module type PT = sig type t val to_string: t -> string end module A(P:PT) = struct module SubA = struct type t = T of P.t | F of float end end 我想用include扩展它。这甚至起作用: module Aplus(P:PT) = struct i

我有一个函子,它有一个子模块:

module type PT = sig
    type t       
    val to_string: t -> string
end

module A(P:PT) = struct
    module SubA = struct
        type t = T of P.t | F of float
    end
end
我想用include扩展它。这甚至起作用:

module Aplus(P:PT) = struct
    include A(P)
    let print x = print_string (P.to_string x)
end
但由于某些原因,它不适用于子模块

module Aplus(P:PT) = struct
    include A(P)
    let print x = print_string (P.to_string x)
    module SubAplus = struct
        include A(P).SubA (* Syntax error here *)
    end
end
在函子应用程序之后,子模块引用出现
语法错误
,失败。这很奇怪,因为语言语法似乎允许这样做。有什么具体的理由不允许这样做吗?

很简单:

module M = F(A)
include M.SubModule
有各种可能的原因,但一个简单的原因是:如果函子应用程序
F(A)
的结果模块没有命名,您将无法引用它。如果函数在上下文中引入类型相等,则会导致问题(特别是在错误消息中…)

注意,可以使用类型、模块类型和类类型来实现
F(M).M.t
是一个完全有效的类型表达式

要完成此操作,在您的情况下,不需要重新应用函子,您之前已经应用了函子,因此
包含SubA
就足够了。

OCaml在模块路径中,只允许您引用模块类型、类型构造函数和类型:

对于引用类型构造函数、模块类型或类类型 前缀还可以包含简单的函子应用程序(如 如果定义 模块是函子应用程序的结果


换句话说,要访问实际值,您需要实例化模块,然后可以引用任何值。有关完整的示例,请参见Drup的答案

仅对类型、模块类型和类类型使用值是不可能做到这一点的。