# How to use Core.Tuple2 as a Core.Map key

**URL:** https://discuss.ocaml.org/t/how-to-use-core-tuple2-as-a-core-map-key/3020
**Category:** Learning
**Tags:** core
**Created:** [December 7, 2018, 4:05am UTC](https://discuss.ocaml.org/t/how-to-use-core-tuple2-as-a-core-map-key/3020 "2018-12-07T04:05:41Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![alejandro](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/alejandro/32/1047_2.png) [@alejandro](https://discuss.ocaml.org/u/alejandro)
#### Post date: [December 7, 2018, 4:05am UTC](https://discuss.ocaml.org/t/how-to-use-core-tuple2-as-a-core-map-key/3020/1 "2018-12-07T04:05:41Z")

</div>

Using `Core`, I’m trying to make a map keyed by tuples of integers. I understand how to do something like `Map.empty (module String)`, but I don’t understand what’s going on fundamentally well enough to know how to make this work for something like `Map.empty (module Tuple2)`; I assume that I need to somehow parameterize Tuple2 with the types of its members, but I can’t figure out the syntax to do it.

I worked around it by making my own module, but that feels suboptimal

```auto
module Foo = struct
  module IntTuple = struct
    type t = int * int
    let compare (x0, y0) (x1, y1) =
      match Pervasives.compare x0 x1 with
        0 -> Pervasives.compare y0 y1
      | c -> c

    let t_of_sexp tuple = Tuple2.t_of_sexp Int.t_of_sexp Int.t_of_sexp tuple
    let sexp_of_t tuple = Tuple2.sexp_of_t Int.sexp_of_t Int.sexp_of_t tuple
  end
  include IntTuple
  include Comparable.Make(IntTuple)
end

```

Given the above

```auto
let a = Map.empty (module Foo);; (* works as expected *)

let b = Map.empty (module (int, int) Tuple2);; (* doesn't compile *),
```

---

<div class="post-metadata">

### Author: ![struktured](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/struktured/32/385_2.png) [@struktured](https://discuss.ocaml.org/u/struktured)
#### Post date: [December 7, 2018, 4:44am UTC](https://discuss.ocaml.org/t/how-to-use-core-tuple2-as-a-core-map-key/3020/2 "2018-12-07T04:44:48Z")

</div>

The line `include Comparable.Make(IntTuple)` injects several data structures specialized on `Foo.IntTuple` into module `Foo`. One of them happens to be an ordered map. You’re supposed to just use that module as it doesn’t require working with first class ones.

For example, you can add an element to the map and get it back with the following snippet:

```auto
let map = Foo.Map.(add_exn empty ~key:(1,2) ~data:"hello") in Foo.Map.find map (1,2)

```

The style you were attempting (`Map.empty (module Foo)`) is heavier than using just `Foo.Map` and requires a first class module with a comparator and comparator witness.

`Foo.Tuple2` does not define these values, but `Foo` does via `include Comparable.Make(IntTuple)`. Also, [Tuple2](https://ocaml.janestreet.com/ocaml-core/latest/doc/core_kernel/Core_kernel/Tuple/T2/), a provided `Core` module is _not_ the same as submodule `Foo.Tuple2`. Both of them won’t work however with `Map.empty`.

Hope this helps!

_PS_:

- You should probably mention you’re using `Core` when posting issues of this nature. It might help people understand your problem a bit quicker.

- `(int,int) module Tuple2` is nonsensical because modules do not accept type parameters. While this isn’t quite the same, you could define a type like this: `type 'a t = 'a * (module T with type t = 'a)`.

- Consider doing `type t = (int * int) [@@deriving sexp, compare]` to automatically generate the serializers and comparator. It requires the `ppx_jane` preprocessor which is easy to setup with dune.

---

<div class="post-metadata">

### Author: ![alejandro](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/alejandro/32/1047_2.png) [@alejandro](https://discuss.ocaml.org/u/alejandro)
#### Post date: [December 7, 2018, 1:40pm UTC](https://discuss.ocaml.org/t/how-to-use-core-tuple2-as-a-core-map-key/3020/3 "2018-12-07T13:40:20Z")

</div>

Thanks for replying! I edited the question to call out core specifically. I guess I’m still wondering whether there is any way to use Core.Tuple2 to save myself from having to type out any of that definition above? It seems unfortunate that everyone who wants to use a map of tuple has to define their own tuple module, and can’t benefit from what’s built into Core.Tuple2.

---

<div class="post-metadata">

### Author: ![struktured](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/struktured/32/385_2.png) [@struktured](https://discuss.ocaml.org/u/struktured)
#### Post date: [December 7, 2018, 5:27pm UTC](https://discuss.ocaml.org/t/how-to-use-core-tuple2-as-a-core-map-key/3020/4 "2018-12-07T17:27:11Z")

</div>

Perhaps the following way to create a tuple map is short enough to suit your tastes?

```auto

module M = Map.Make(struct type t = int * int [@@deriving sexp, compare] end)

let map = M.(empty |> add_exn ~key:(1,2) ~data:"hello")

```

---

<div class="post-metadata">

### Author: ![alejandro](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/alejandro/32/1047_2.png) [@alejandro](https://discuss.ocaml.org/u/alejandro)
#### Post date: [December 7, 2018, 9:00pm UTC](https://discuss.ocaml.org/t/how-to-use-core-tuple2-as-a-core-map-key/3020/5 "2018-12-07T21:00:03Z")

</div>

Yeah that’s nice and short, but it sounds like the answer to my question is no. i.e. once a module has been defined (like Core.Tuple2), there’s no way to make it work as a key for Core.Map if it wasn’t created with that intention specifically?

I’m coming at this from something like clojure, where it’s fairly easy to extend existing code and ‘types’ with new functionality, even if someone else defined them. I was hoping ocaml’s module system would let me do something similar. Or maybe I’m misunderstanding something even more fundamental… 🤔

---

<div class="post-metadata">

### Author: ![Levi\_Roth](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/levi_roth/32/2268_2.png) [@Levi\_Roth](https://discuss.ocaml.org/u/Levi_Roth)
#### Post date: [December 7, 2018, 9:49pm UTC](https://discuss.ocaml.org/t/how-to-use-core-tuple2-as-a-core-map-key/3020/6 "2018-12-07T21:49:48Z")

</div>

I think you may be looking for the functor `Tuple.Comparable`:

```auto
module Int_tuple = Tuple.Comparable (Int) (Int)

```

As for extending modules written by others, isn’t that what you get with `include`? Maybe I don’t understand what you’re looking for.

---

<div class="post-metadata">

### Author: ![alejandro](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/alejandro/32/1047_2.png) [@alejandro](https://discuss.ocaml.org/u/alejandro)
#### Post date: [December 7, 2018, 10:20pm UTC](https://discuss.ocaml.org/t/how-to-use-core-tuple2-as-a-core-map-key/3020/7 "2018-12-07T22:20:05Z")

</div>

Hmmm, that’s interesting! Those are two good leads I think; I’ll have to do more reading and experimenting.

Thank you @Levi_Roth and @struktured!
