# Core.Map in recursive type

**URL:** https://discuss.ocaml.org/t/core-map-in-recursive-type/2061
**Category:** Learning
**Tags:** core
**Created:** [May 30, 2018, 6:30pm UTC](https://discuss.ocaml.org/t/core-map-in-recursive-type/2061 "2018-05-30T18:30:06Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![ins](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ins/32/923_2.png) [@ins](https://discuss.ocaml.org/u/ins)
#### Post date: [May 30, 2018, 6:30pm UTC](https://discuss.ocaml.org/t/core-map-in-recursive-type/2061/1 "2018-05-30T18:30:06Z")

</div>

I’m trying to use a `Core.Map` inside a recursive ADT as follows:

```auto
module T = struct
  type t = 
    | TInt of Int.t
    | TString of String.t
    | TMap of (t, t, _) Map.t

  let sexp_of_t = ...
  let compare = ...
end

include T
include Comparator.Make(T)

```

I’m not sure what to provide for the `comparator_witness` which is the third type argument for `Map.t`. I am used to getting the `comparator_witness` from `Comparator.Make(T)`. Is there a standard way to do this?

A separate but related question: is `@@deriving` able to derive `compare` for ADTs involving `Core.Map`? I suspect not, but I haven’t tried due to the issue above.

---

<div class="post-metadata">

### Author: ![bcc32](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bcc32/32/203_2.png) [@bcc32](https://discuss.ocaml.org/u/bcc32)
#### Post date: [May 31, 2018, 12:11am UTC](https://discuss.ocaml.org/t/core-map-in-recursive-type/2061/2 "2018-05-31T00:11:36Z")

</div>

Unfortunately, I haven’t worked out how to make `[@@deriving compare]` work with `Core.Map` because `Map.compare` is not defined (there is `Map.compare_direct` which I haven’t really figured out what it’s for). I had similar problems with `[@@deriving sexp]`.

That being said, I think I worked out how to make a terrible hack compile, using recursive modules (the horror!):

```ocaml
open! Core

module T : sig
  type t [@@deriving sexp_of]

  include Comparable.S_plain with type t := t
end = struct
  module rec T1 : sig
    type t =
      | TInt of Int.t
      | TString of String.t
      | TMap of (t, t, T1.comparator_witness) Map.t
    [@@deriving sexp_of]

    include Comparator.S with type t := t
  end = struct
    module T0 = struct
      type t =
        | TInt of Int.t
        | TString of String.t
        | TMap of (t, t, T1.comparator_witness) Map.t

      let rec compare a b =
        match a, b with
        | TInt x, TInt y -> Int.compare x y
        | TInt _, _ -> -1
        | TString x, TString y -> String.compare x y
        | TString _, TInt _ -> 1
        | TString _, TMap _ -> -1
        | TMap x, TMap y -> Map.compare_direct compare x y
        | TMap _, _ -> 1
      ;;

      let sexp_of_t = sexp_of_opaque
    end
    include T0
    include Comparator.Make(T0)
  end
  include T1
  include Comparable.Make_plain_using_comparator(T1)
end

```

Basically, the hack is needed because the type definition for `t` requires the `comparator_witness` generated by `Comparator.Make`, before that functor has been applied. At least, I didn’t find a way around this but maybe somebody else could chime in?

---

<div class="post-metadata">

### Author: ![ins](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ins/32/923_2.png) [@ins](https://discuss.ocaml.org/u/ins)
#### Post date: [May 31, 2018, 12:28am UTC](https://discuss.ocaml.org/t/core-map-in-recursive-type/2061/3 "2018-05-31T00:28:16Z")

</div>

Wow! Thanks for going through the trouble.

I also came up with a (very scary) solution using recursive modules. I was hoping there was some trick I was missing.

As for `@@deriving`, I think `compare_direct` is precisely what you would want for a default total order over `Core.Map`s, but the trouble is you need a total order (`compare`) over the values in the map.

I have no experience writing `ppx` stuff so I don’t know what’s involved, but if the issue is just that you need to grab a sensible total order for `Core.Map` then I think `compare_direct` is what you want.

---

<div class="post-metadata">

### Author: ![smolkaj](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/smolkaj/32/266_2.png) [@smolkaj](https://discuss.ocaml.org/u/smolkaj)
#### Post date: [May 31, 2018, 2:28am UTC](https://discuss.ocaml.org/t/core-map-in-recursive-type/2061/4 "2018-05-31T02:28:48Z")

</div>

You may want to take a look at Base.Map instead. You should be able to derive things like so;

```auto
type t = Map.M(Int).t [@@deriving sexp, compare]

```

---

<div class="post-metadata">

### Author: ![ins](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ins/32/923_2.png) [@ins](https://discuss.ocaml.org/u/ins)
#### Post date: [May 31, 2018, 2:40am UTC](https://discuss.ocaml.org/t/core-map-in-recursive-type/2061/5 "2018-05-31T02:40:08Z")

</div>

Ah, interesting. Reading the [docs for `Map.M`](https://ocaml.janestreet.com/ocaml-core/latest/doc/base/Base/Map/M/) it seems like the `@@deriving` ppx for `compare` tries to grab a total order for all the type arguments, and the issue is that `comparator_witness` obviously wont have one.

I guess for maps with equal keys, the derived compare breaks the tie with polymorphic compare over values?

Anyway, thanks for the pointer! I will use this from now on.
