Question

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)?

Was it helpful?

Solution

The simple answer is to use a transparent signature constraint

structure Reals : Field

rather than an opaque constraint.

structure Reals :> Field

When you use an opaque constraint types such as field_type in the signature are created as new types distinct from the types that are used to implement them. If you want to retain the link to the original type you need to use a transparent constraint. With a transparent constraint Reals.field_type and real are the same type so you can use

ReF.add(0.0, 0.0);

perfectly well.

> ReF.add(0.0, 0.0);
val it = 0.0: real

As an alternative to using a transparent constraint, if you have other types in your signature that you want to be created as new types, you can still get the desired effect by using an opaque constraint along with where type.

structure Reals :> Field where type field_type = real
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top