I want to create a struct which is based on another struct whose implementation can be switched.
signature Field =
sig
type field_type;
val zero : field_type;
val add : (field_type * field_type) -> field_type;
val f : int -> field_type;
end;
structure Reals :> Field =
struct
type field_type = real;
val zero = 0.0;
fun add (x,y) = x + y;
fun f x = Real.fromInt(x);
end;
structure Rat :> Field =
struct
type field_type = int * int;
val zero = (0, 1);
fun add ((i1,i2),(j1,j2)) = (i1*j2 + j1*i2, i2*j2);
fun f x = (x, 1);
end;
functor Useable(F : Field) =
struct
type field_type = F.field_type;
val zero = F.zero;
fun add(x,y) = F.add(x,y);
fun f x = F.f x;
end;
structure ReF = Useable(Reals);
structure RaF = Useable(Rat);
The idea is that I could plug in implementations of Field (Reals or Rat, ignore the inefficient implementations).
I can run this code ReF.add(ReF.zero, ReF,zero)
, but can't run ReF.add(0.0, 0.0)
(or RaF.add((0,1),(0,1))
)
To overcome this I created a constructor f: int -> field_types
, but I found this to be not so elegant and also cumbersome. Can I do anything for being able to use ReF.add(0.0, 0.0)
?