1# Equality
2
3## Structural Equality by Default
4
5In v3, `Equal.equals` used **reference equality** for plain objects and arrays.
6Structural comparison was only available inside a `structuralRegion`, which
7temporarily enabled deep comparison. Outside a structural region, two distinct
8objects with identical contents were not considered equal:
9
10```ts
11// v3
12import { Equal } from "effect"
13
14Equal.equals({ a: 1 }, { a: 1 }) // false — reference equality
15Equal.equals([1, 2], [1, 2]) // false — reference equality
16```
17
18In v4, `Equal.equals` uses **structural equality** by default. Plain objects,
19arrays, `Map`s, `Set`s, `Date`s, and `RegExp`s are compared by value without
20opting in:
21
22```ts
23// v4
24import { Equal } from "effect"
25
26Equal.equals({ a: 1 }, { a: 1 }) // true
27Equal.equals([1, [2, 3]], [1, [2, 3]]) // true
28Equal.equals(new Map([["a", 1]]), new Map([["a", 1]])) // true
29Equal.equals(new Set([1, 2]), new Set([1, 2])) // true
30```
31
32Objects that implement the `Equal` interface continue to use their custom
33equality logic, same as v3.
34
35## Opting Out: `byReference`
36
37If you need reference equality for a specific object, v4 provides
38`Equal.byReference` and `Equal.byReferenceUnsafe`:
39
40```ts
41import { Equal } from "effect"
42
43const obj = Equal.byReference({ a: 1 })
44Equal.equals(obj, { a: 1 }) // false — reference equality
45```
46
47- **`byReference(obj)`** — creates a `Proxy` that uses reference equality,
48 leaving the original object unchanged.
49- **`byReferenceUnsafe(obj)`** — marks the object itself for reference
50 equality without creating a proxy. More performant but permanently changes
51 how the object is compared.
52
53## `NaN` Equality
54
55In v3, `Equal.equals(NaN, NaN)` returned `false` (following IEEE 754).
56In v4, `NaN` is considered equal to `NaN`:
57
58```ts
59Equal.equals(NaN, NaN) // v3: false, v4: true
60```
61
62## `equivalence` → `asEquivalence`
63
64The function that wraps `equals` as an `Equivalence` has been renamed:
65
66```ts
67// v3
68Equal.equivalence<number>()
69
70// v4
71Equal.asEquivalence<number>()
72```