Suppose we want a set of unique { x, y }
points to plot on a graph.
this expression:
new Set([
{ x: 1, y: 1 },
{ x: 1, y: 1 },
]);
evaluates to: Set { { x: 1, y: 1}, { x : 1, y: 1} }
which is likely not what we want.
Let's see the signature of the same constructor in the Set module contained in the fp-ts library:
declare const fromArray: <A>(E: Eq<A>) => (as: Array<A>) => Set<A>;
where the Eq
typeclass is defined as:
interface Eq<A> {
readonly equals: (x: A, y: A) => boolean;
}
Thus, fromArray
takes first an Eq
instance where it is up to the consumer to specify the meaning of the equivalence in his particular domain.
interface Point {
x: number;
y: number;
}
const eqPoint: Eq<Point> = {
equals: (p1, p2) => p1 === p2 || (p1.x === p2.x && p1.y === p2.y),
};
We have defined what does it means for two points to be equal. They are either the same point (by reference), or they have the same coordinates
fromArray(eqPoint)([
{ x: 1, y: 1 },
{ x: 1, y: 1 },
]);
Now correctly evaluates to Set { { x: 1, y: 1} }
Takeaway: the concept of equivalence is vague and it is often a good idea to encode it's meaning in our domain business.
A little bit of improvement: