我可以只为某些函子参数定义OCaml函数吗?

我可以只为某些函子参数定义OCaml函数吗?,ocaml,Ocaml,我想这样做: module Make (M: MInt) (N: MInt) : T = struct (* always defined *) let foo = 42 (* only defined when M == N or M.x == N.x, something like that *) let bar a b = a * b end 这可能吗 显然,我可以在运行时进行检查,但我很好奇如何在编译时进行检查。谢谢 不,我认为函子的结果模块的字段列表

我想这样做:

module Make (M: MInt) (N: MInt) : T = struct
    (* always defined *)
    let foo = 42

    (* only defined when M == N or M.x == N.x, something like that *)
    let bar a b = a * b
end
这可能吗


显然,我可以在运行时进行检查,但我很好奇如何在编译时进行检查。谢谢

不,我认为函子的结果模块的字段列表(签名)不可能以这种方式依赖于参数模块。我认为你能得到的唯一一种依赖是类型替换。

要编码这种东西,你需要一种语言。依赖类型是类型系统的一个强大功能,但不幸的是,它使语言复杂化,并使类型推理不可判定。通常,这比一般程序员愿意支付的费用要多得多。如果您真的想要一种语言来编写这样的规范,那么您需要尝试

OCaml仍然支持某种程度上受限的依赖类型。因此,理论上,在OCaml中可以对函数进行编码,这种类型确保两个参数是相等的整数。为此,您需要使用Peano数字而不是内置整数,或者使用phantom类型注释内置整数,描述其大小。但这一切都是不切实际的。在Coq中编写此代码,然后将定义提取为OCaml程序要容易得多


总而言之,在函子级别上不可能做你想做的事情。使用OCaml类型的系统来表达这样的事情是可能的。但最好使用Coq,并在OCaml中保持简单。

可以有第二个函子扩展第一个函子,但要求模块相等:

module Make (M: MInt) (N: MInt) : T = struct
    let foo = 42
end

module Make2 (M: MInt) : T2 = struct
    include Make(M)(M)

    let bar a b = a * b
end