<A>(): Equivalence<A>Wraps equals as an Equivalence<A>.
When to use
Use when you want to pass Equal.equals to APIs that require an
Equivalence.
Details
- Returns a function
(a: A, b: A) => booleanthat delegates to equals. - Pure; allocates a thin wrapper on each call.
Example (Deduplicating with Equal semantics)
import { Array, Equal } from "effect"
const eq = Equal.asEquivalence<number>()
const result = Array.dedupeWith([1, 2, 2, 3, 1], eq)
console.log(result) // [1, 2, 3]export const const asEquivalence: <
A
>() => Equivalence<A>
Wraps
equals
as an Equivalence<A>.
When to use
Use when you want to pass Equal.equals to APIs that require an
Equivalence.
Details
- Returns a function
(a: A, b: A) => boolean that delegates to
equals
.
- Pure; allocates a thin wrapper on each call.
Example (Deduplicating with Equal semantics)
import { Array, Equal } from "effect"
const eq = Equal.asEquivalence<number>()
const result = Array.dedupeWith([1, 2, 2, 3, 1], eq)
console.log(result) // [1, 2, 3]
asEquivalence: <function (type parameter) A in <A>(): Equivalence<A>A>() => type Equivalence<in A> = (self: A, that: A) => booleanRepresents an equivalence relation over type A.
When to use
Use as a type annotation when you accept or return an equivalence function.
Details
- Returns
boolean: true if values are equivalent, false otherwise
- Must satisfy reflexive, symmetric, and transitive properties
Example (Defining simple number equivalence)
import type { Equivalence } from "effect"
const numberEq: Equivalence.Equivalence<number> = (a, b) => a === b
console.log(numberEq(1, 1)) // true
console.log(numberEq(1, 2)) // false
Example (Defining custom object equivalence)
import type { Equivalence } from "effect"
interface Point {
x: number
y: number
}
const pointEq: Equivalence.Equivalence<Point> = (a, b) =>
a.x === b.x && a.y === b.y
console.log(pointEq({ x: 1, y: 2 }, { x: 1, y: 2 })) // true
Equivalence<function (type parameter) A in <A>(): Equivalence<A>A> = () => function equals<B>(that: B): <A>(self: A) => boolean (+1 overload)Checks whether two values are deeply structurally equal.
When to use
Use when you need Effect's default structural equality check.
Details
Returns a boolean and never throws. Primitives are compared by value, and
NaN equals NaN. Objects implementing Equal delegate to their
[Equal.symbol] method; if only one operand implements Equal, the result
is false.
Dates compare by ISO string, RegExps compare by string representation,
arrays compare element-by-element, Maps and Sets compare entries
order-independently, and plain objects compare enumerable keys recursively.
Functions without an Equal implementation compare by reference. Circular
references are handled when both structures are circular at the same depth.
Hash values are checked first as a fast-path rejection. The function also
supports dual data-last usage: call it with one argument to get a curried
predicate.
Gotchas
- Results are cached per object pair in a WeakMap. Objects must not be
mutated after their first comparison.
- Map and Set comparisons are O(n²) in size.
Example (Comparing values)
import { Equal } from "effect"
// Primitives
console.log(Equal.equals(1, 1)) // true
console.log(Equal.equals(NaN, NaN)) // true
console.log(Equal.equals("a", "b")) // false
// Objects and arrays
console.log(Equal.equals({ a: 1, b: 2 }, { a: 1, b: 2 })) // true
console.log(Equal.equals([1, [2, 3]], [1, [2, 3]])) // true
// Dates
console.log(Equal.equals(new Date("2024-01-01"), new Date("2024-01-01"))) // true
// Maps (order-independent)
const m1 = new Map([["a", 1], ["b", 2]])
const m2 = new Map([["b", 2], ["a", 1]])
console.log(Equal.equals(m1, m2)) // true
// Curried form
const is5 = Equal.equals(5)
console.log(is5(5)) // true
console.log(is5(3)) // false
equals