trite.io - posts

Using Relude's `Set.t` functionality

Created: December 18, 2022

While working on Day 09 of Advent of Code in ReasonML with Relude as a standard library and Melange to compile I found it a bit painful to figure out how to use Set with a custom type structure.

How to use Relude.Set in ReasonML

You need to tell Set how to compare items in order for it to be able to properly order its items and guarantee they are distinct. This can be done by creating a custom type and leveraging Set.WithOrd to wire up the comparison and equality functionality like so:

module Position = {
  type t = (int, int);

  let compare = ((x1, y1), (x2, y2)) =>
    switch(Int.compare(x1, x2)) {
    | `equal_to => Int.compare(y1, y2)
    | other => other
    };

  let eq = (t1, t2) =>
    compare(t1, t2) == `equal_to;

  module Ord = {
    type nonrec t = t;
    let compare = compare;
    let eq = eq;
  }
  module Set = Set.WithOrd(Ord);
};

Once that’s done you can create an empty set and add items to it quite easily:

Position.Set.empty
|> Position.Set.add((0, 0))
|> Position.Set.add((12, 34))
|> Position.Set.add((42, 42))
|> Position.Set.add((0, 0))
|> Position.Set.toArray
|> Js.log;

Running this will result in a set with only 3 items in it, despite adding to it 4 times, since (0, 0) is added twice:

1
2
$ node _build/default/src/PositionSetTest.bs.js
[ [ 0, 0 ], [ 12, 34 ], [ 42, 42 ] ]