ethanabrooks
ethanabrooks

Reputation: 777

How to satisfy module type including polymorphic set

I am trying to create a module that exposes a set without exposing the type of the elements in the set. Here is a simplified version:

open Core

module type M_t = sig
  module Id : Comparator.S

  val set : (Id.t, Id.comparator_witness) Set_intf.Tree.t
end

module M : M_t = struct
  module Id = Int
  module S = Set.Make (Id)

  let set = S.empty
end

With this signature, client applications could use the M_t signature and not know that under the hood, set contains ints. Not only is my implementation not particularly idiomatic, but it doesn't compile:

❯ dune build
File "hello_world.ml", lines 9-14, characters 17-3:
 9 | .................struct
10 |   module Id = Int
11 |   module S = Set.Make (Id)
12 | 
13 |   let set = S.empty
14 | end
Error: Signature mismatch:
       ...
       Values do not match:
         val set : S.t
       is not included in
         val set : (int, Id.comparator_witness) Set_intf.Tree.t
       File "hello_world.ml", line 6, characters 2-57: Expected declaration
       File "hello_world.ml", line 13, characters 6-9: Actual declaration

I have found everal similar questions but I haven't succeeded in transferring the answers to my setting, so I apologize if this is a duplicate.

Upvotes: 1

Views: 44

Answers (1)

Lhooq
Lhooq

Reputation: 4441

The solution I could come up with is the following:

open Core

module type M_t = sig
  module Id : Comparator.S

  module S : Set.S with type Elt.t = Id.t

  val set : S.t
end

module M : M_t = struct
  module Id = Int
  module S = Set.Make (Id)

  let set = S.empty
end

The thing is I couldn't find a way to force Elt.comparator_witness to be equal to Id.comparator_witness and this is the closest working solution I got to correspond to your initial problem (I'm not a Core user).

Upvotes: 1

Related Questions