Core_kernel Comparator and polymorphism

OCaml newbie here. I’ve run into a problem I’m struggling to resolve.

I’m working on an existing codebase, and I’d like to refactor one of its functions, which has the interface:

let do_something (l : 'a list) : 'a list = ...

This function is called with arguments of several different types, and its current implementation depends on polymorphic comparison.

I’d like to refactor it to call Core_kernel.Set’s stable_dedup_list, which takes a comparator argument of type ('a, 'b) Comparator.t.

My question: is there a way to pass a polymorphic Comparator here so that do_something can keep the same polymorphic interface? I’m imagining something that would be used like this:

Core_kernel.Set.stable_dedup_list (module Comparator.Poly(??)) my_list;;

Or is there a better way to go about this?
Ideally I’d like to get rid of the polymorphic comparison someday, which I assume would require passing down the appropriate comparator at every callsite. But I’d like to avoid that for now, if possible.

Just looking at the signature it looks like you could use

Core_kernel.Set.stable_dedup_list ~comparator:Comparator.Poly.comparator my_list

Cheers,
Nicolás

Thanks for the reply. When I pass Comparator.Poly.comparator, I get the error

Error: This expression has type
         ('a, Comparator.Poly.comparator_witness) Comparator.t
       but an expression was expected of type
         ('b, 'c) Set.comparator =
           (module Core_kernel__.Comparator.S with type comparator_witness = 'c and type t = 'b)

My apologies, I may have been looking at the wrong docs when I quoted the type for comparator, which is actually ('a, 'b) Set.comparator .

OK, two options:

  1. use Core_kernel.Using_comparator.stable_dedup_list: this function takes a _ Comparator.t as the ~comparator argument, or
  2. to use Core_kernel.Set.stable_dedup_list, which takes a Comparator.S as the ~comparator argument, do something along the lines:
open Core_kernel
let do_something (type a) (l : a list) =
  let module C = struct include Comparator.Poly type t = a end in
  Set.stable_dedup_list (module C) l;;

Cheers,
Nicolás

2 Likes

That works. Thanks so much for your help!!

I hadn’t yet seen locally abstract types, so thanks for introducing me to them–gonna go read about them in Real World OCaml now :slight_smile: