Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract common functions from 2 functors

I have defined a module type ZONE and two functors (ZoneFun and ZoneFunPrec) to build it:

(* zone.ml *)
module type ZONE =
sig
  type info
  type prop
  type t = { p: prop; i: info }
  val f1 : t -> string
end

module ZoneFun (Prop : PROP) = struct
  type info = { a: int }
  type prop = Prop.t
  type t = { p: prop; i: info }
  let f1 z = "f1"
end

(* zoneFunPrec.ml *)
module ZoneFunPrec (Prop: PROP) (Prec: ZONESM) = struct
  type info = { a: int; b: Prec.t }
  type prop = Prop.t
  type t = { p: prop; i: info }
  let f1 z = "f1"
  let get_prec z = z.info.prec
end   

Some functions in these 2 functors are implemented differently (e.g. f0); some functions are exactly the same (e.g. f1). My question is how to extract those common functions to avoid from implementing them twice?

Edit: (I realize that I need to give more specific information to make it clearer... Sorry about the change...)

There are some differences between ZoneFun and ZoneFunPrec:

1) their type info are not same 2) ZoneFunPrec has get_prec that ZoneFun doesn't have, and the signture of ZONE doesn't require it.

So later I can write module ZoneB = ZoneFun(B) and module ZoneA = ZoneFunPrec(C)(ZonesmD) to build the zones...

like image 945
SoftTimur Avatar asked Nov 12 '22 22:11

SoftTimur


1 Answers

You can do the following:

module ZoneFunPrec (Prop: PROP) = struct
  module Zone1 = ZoneFun(Prop)
  type prop = Prop.t
  type t = string
  let f0 x = "f0 in ZoneFunPrec"
  let f1 = Zone1.f1
end

But this will only work if you do not ascribe the signature in the functor

module ZoneFunPrec (Prop: PROP) : ZONE = ...

If you want opaque ascription, you could do something like this

(* No ascription here *)
module SharedFn (Prop : PROP) = struct
  type prop = Prop.t
  type t = string
  let f0 x = "f0 in ZoneFun"
  let f1 x = "f1"
end

(* Ascribe the module to hide the types *)  
module ZoneFun (Prop : PROP) : ZONE = struct
  module Shared = SharedFn(Prop)
  let f1 = Shared.f1
  ...defs specific to ZONE...
end 

module ZoneFunPrec (Prop: PROP) : ZONE_PREC = struct
  module Shared = SharedFn(Prop)
  type prop = Prop.t
  type t = string
  let f0 x = "f0 in ZoneFunPrec"
  let f1 = Shared.f1
  ...defs specific to ZONE_PREC...
end

You can try using include Shared to save typing, but the types will be abstract so it won't be very flexible.

like image 106
seanmcl Avatar answered Nov 15 '22 06:11

seanmcl