smithery.ai

traits

This skill should be used when the user asks about "Effect Equal", "Effect Hash", "Equivalence", "Order", "structural equality", "custom equality", "comparing objects", "sorting", "Equal.equals", "Hash.hash", "Equivalence.make", "Order.lessThan", "comparable types", or needs to understand how Effect handles equality, hashing, and ordering of values.

First seen Apr 17, 2026

Installation

$ npx skills add https://smithery.ai

Summary

This skill should be used when the user asks about "Effect Equal", "Effect Hash", "Equivalence", "Order", "structural equality", "custom equality", "comparing objects", "sorting", "Equal.equals", "Hash.hash", "Equivalence.make", "Order.lessThan", "comparable types", or needs to understand how Effect handles equality, hashing, and ordering of values.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 7,289 B
  • docs SUMMARY.md 365 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

Traits in Effect

Overview

Effect provides trait-based abstractions for:

  • Equal - Structural equality comparison
  • Hash - Hash code generation
  • Equivalence - Custom equality relations
  • Order - Ordering and comparison

These enable consistent behavior across Effect's data structures.

Equal - Structural Equality

The Equal Interface

import { Equal } from "effect";

Equal.equals(a, b);

import { Data } from "effect";

class Person extends Data.Class<{
  name: string;
  age: number;
}> {}

const p1 = new Person({ name: "Alice", age: 30 });
const p2 = new Person({ name: "Alice", age: 30 });

Equal.equals(p1, p2);
p1 === p2;

Implementing Equal (Recommended: Use Data.Class)

PREFER Data.Class which provides Equal and Hash automatically:

import { Data, Equal } from "effect";

// Data.Class provides Equal and Hash automatically
class Point extends Data.Class<{ readonly x: number; readonly y: number }> {}

const p1 = new Point({ x: 1, y: 2 });
const p2 = new Point({ x: 1, y: 2 });

Equal.equals(p1, p2);

For Schema types, use Schema.Class which also provides Equal:

import { Schema, Equal } from "effect";

class Point extends Schema.Class<Point>("Point")({
  x: Schema.Number,
  y: Schema.Number,
}) {}

const p1 = new Point({ x: 1, y: 2 });
const p2 = new Point({ x: 1, y: 2 });

Equal.equals(p1, p2); // true

Why Equal Matters

Effect's collections (HashMap, HashSet) use Equal for lookups:

import { HashMap, Data } from "effect";

class UserId extends Data.Class<{ id: string }> {}

const map = HashMap.make([
  [new UserId({ id: "1" }), "Alice"],
  [new UserId({ id: "2" }), "Bob"],
]);

// Works because UserId implements Equal
HashMap.get(map, new UserId({ id: "1" })); // Option.some("Alice")

Hash - Hash Code Generation

The Hash Interface

import { Hash } from "effect";

Hash.hash(value);

Hash.string("hello");
Hash.number(42);
Hash.combine(h1)(h2);
Hash.array([1, 2, 3]);

Hash Contract

Objects that are Equal MUST have the same hash:

// If Equal.equals(a, b) === true
// Then Hash.hash(a) === Hash.hash(b)

// The reverse is NOT required:
// Same hash does NOT mean equal (hash collisions are allowed)

Hash with Data.Class (Recommended)

Data.Class provides both Equal and Hash automatically:

import { Data, Hash, Equal } from "effect";

class Rectangle extends Data.Class<{
  readonly width: number;
  readonly height: number;
}> {}

const r1 = new Rectangle({ width: 10, height: 5 });
const r2 = new Rectangle({ width: 10, height: 5 });

Equal.equals(r1, r2);
Hash.hash(r1) === Hash.hash(r2);

Equivalence - Custom Equality Relations

Creating Equivalences

import { Equivalence } from "effect";

const caseInsensitive = Equivalence.make<string>((a, b) => a.toLowerCase() === b.toLowerCase());

caseInsensitive("Hello", "hello");
caseInsensitive("Hello", "HELLO");

Equivalence.string;
Equivalence.number;
Equivalence.boolean;
Equivalence.strict;

Transforming Equivalences

// Map to compare by derived value
const byLength = Equivalence.string.pipe(Equivalence.mapInput((s: string) => s.length.toString()));

// Actually, better approach:
const byLength = Equivalence.make<string>((a, b) => a.length === b.length);

// Combine equivalences
const userEquivalence = Equivalence.make<User>(
  (a, b) => Equivalence.string(a.name, b.name) && Equivalence.number(a.age, b.age),
);

Using with Collections

import { Array as Arr } from "effect";

const users = [
  { name: "Alice", age: 30 },
  { name: "Bob", age: 25 },
  { name: "alice", age: 30 }, // Same as Alice?
];

// Dedupe with custom equivalence
const byNameIgnoreCase = Equivalence.make<User>((a, b) => a.name.toLowerCase() === b.name.toLowerCase());

const unique = Arr.dedupe(users); // Uses default equality
const uniqueByName = Arr.dedupeWith(users, byNameIgnoreCase);

Order - Comparison and Sorting

The Order Interface

import { Order } from "effect";

Order.string("a", "b");
Order.string("b", "a");
Order.string("a", "a");

Order.lessThan(Order.number)(5, 10);
Order.greaterThan(Order.number)(5, 10);
Order.lessThanOrEqualTo(Order.number)(5, 5);
Order.between(Order.number)({ minimum: 0, maximum: 10 })(5);

Order.min(Order.number)(3, 7);
Order.max(Order.number)(3, 7);

Order.clamp(Order.number)({ minimum: 0, maximum: 100 })(150);

Built-in Orders

Order.string;
Order.number;
Order.boolean;
Order.bigint;
Order.Date;

Creating Custom Orders

const byAge = Order.make<Person>((a, b) => (a.age < b.age ? -1 : a.age > b.age ? 1 : 0));

const byName = Order.mapInput(Order.string, (p: Person) => p.name);
const byAge = Order.mapInput(Order.number, (p: Person) => p.age);

Combining Orders

const byAgeThenName = Order.combine(byAge, byName);

const byAgeDesc = Order.reverse(byAge);

const sortUsers = Order.combine(
  Order.mapInput(Order.string, (u: User) => u.department),
  Order.combine(
    Order.reverse(Order.mapInput(Order.number, (u: User) => u.salary)),
    Order.mapInput(Order.string, (u: User) => u.name),
  ),
);

Sorting with Order

import { Array as Arr } from "effect";

const people = [
  { name: "Charlie", age: 35 },
  { name: "Alice", age: 30 },
  { name: "Bob", age: 30 },
];

const byAge = Arr.sort(
  people,
  Order.mapInput(Order.number, (p) => p.age),
);

const sorted = Arr.sort(
  people,
  Order.combine(
    Order.mapInput(Order.number, (p) => p.age),
    Order.mapInput(Order.string, (p) => p.name),
  ),
);

Data.Class - Automatic Implementation

Using Data.Class automatically implements Equal and Hash:

import { Data, Equal, Hash } from "effect";

class User extends Data.Class<{
  id: string;
  name: string;
  email: string;
}> {}

const u1 = new User({ id: "1", name: "Alice", email: "[email protected]" });
const u2 = new User({ id: "1", name: "Alice", email: "[email protected]" });

Equal.equals(u1, u2); // true
Hash.hash(u1) === Hash.hash(u2); // true

Best Practices

  1. Use Data.Class for value objects - Automatic Equal/Hash
  2. Implement both Equal and Hash together - Required for collections
  3. Use Order.mapInput for simple ordering - Cleaner than manual comparison
  4. Combine orders for complex sorting - More composable than custom compare
  5. Consider Equivalence for custom equality - When default equality isn't enough

Additional Resources

For comprehensive trait documentation, consult ${CLAUDEPLUGINROOT}/references/llms-full.txt.

Search for these sections:

  • "Equal" for equality comparison
  • "Hash" for hash code generation
  • "Equivalence" for custom equality relations
  • "Order" for ordering and comparison