Is there a way to either parametrize a module on a type or escape a type from a module in OCaml? Basically, I'd like to write some routines that are parametrized on a floating point type and still have access to the operators like (+.), (-.), etc. Certainly, we can write a floating point module like
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
which has a really basic implementation for normal floats
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
Then, I tried to use this module locally in a module with the code
let double (type real) (module Real:REAL with type t = real) x =
let open Real in
x+.x
This function has the type that I desire
val double : (module REAL with type t = 'a) -> 'a -> 'a = <fun>
However, if I run it, the compiler will complain
# double (module MyReal) 1.0;;
Error: This expression has type float but an expression was expected of type
MyReal.t
Certainly, we can use the injection function from the module
# double (module MyReal) (MyReal.real 1.0);;
- : MyReal.t = <abstr>
but then the resulting type is abstract and not a float. Ultimately, I'd like a way to have the function double return an exposed type. If at all possible, I don't want to use another function within the REAL module to convert t->float
. I want the actual type t
to be exposed somehow. Also, I'd like a way to do this by using the module locally rather than a functor parameterized on REAL
.
You gave
MyReal
a type constraint too restricted:MyReal : REAL
. It's typet
's implementation is hidden by the constraint. At the use ofMyReal
,double (module MyReal) 1.0
, the unification of typet
andfloat
fails since you hide the factt = float
.A fix is the following:
but the best way is to let OCaml infer the most general type for
MyReal
by itself:Here, the relationship of
MyReal
andREAL
is less clear but OCaml's module typing is clever enough to findMyReal
has an instance ofmodule REAL with type t = 'a
.