有没有办法在类型上参数化模块或从OCaml中的模块中转义类型?基本上,我想编写一些在浮点类型上进行参数化的例程,并且仍然可以访问像(+。),( - 。)等运算符。当然,我们可以写一个浮点模块,如
module type REAL = sig
type t
val real : float->t
val (+.) : t->t->t
val (-.) : t->t->t
val ( *. ) : t->t->t
val (/.) : t->t->t
end
对普通浮动有一个非常基本的实现
module MyReal : REAL = struct
type t=float
let real x=x
let (+.) x y = x+.y
let (-.) x y = x-.y
let ( *. ) x y = x*.y
let (/.) x y = x/.y
end
然后,我尝试在具有代码
的模块中本地使用此模块let double (type real) (module Real:REAL with type t = real) x =
let open Real in
x+.x
此功能具有我想要的类型
val double : (module REAL with type t = 'a) -> 'a -> 'a = <fun>
但是,如果我运行它,编译器会抱怨
# double (module MyReal) 1.0;;
Error: This expression has type float but an expression was expected of type
MyReal.t
当然,我们可以使用模块中的注入功能
# double (module MyReal) (MyReal.real 1.0);;
- : MyReal.t = <abstr>
但是结果类型是抽象的而不是浮点数。最终,我想要一种让函数double返回暴露类型的方法。如果可能的话,我不想在REAL模块中使用另一个函数来转换t->float
。我想以某种方式暴露实际类型t
。另外,我想通过在本地使用模块而不是在REAL
上参数化的仿函数来实现此目的。
答案 0 :(得分:3)
您对MyReal
类型约束的限制过于严格:MyReal : REAL
。它的类型t
的实现被约束隐藏。在使用MyReal
,double (module MyReal) 1.0
时,类型t
和float
的统一失败,因为您隐藏了事实t = float
。
修复如下:
module MyReal : REAL with type t = float = struct
...
end
但最好的方法是让OCaml自己推断出MyReal
最常用的类型:
module MyReal = struct
...
end
此处,MyReal
和REAL
的关系不太明确,但OCaml的模块类型非常聪明,可以找到MyReal
的实例module REAL with type t = 'a
。