diff --git a/.changeset/cyan-sloths-lick.md b/.changeset/cyan-sloths-lick.md
index 22789ec9f9..3a8407dea9 100644
--- a/.changeset/cyan-sloths-lick.md
+++ b/.changeset/cyan-sloths-lick.md
@@ -7,3 +7,5 @@ Re-export modules from `effect`.
`ArrayFormatter` / `TreeFormatter` merged into `ParseResult` module.
`Serializable` module merged into `Schema` module.
+
+`Equivalence` module merged into `Schema` module.
diff --git a/.changeset/six-crabs-itch.md b/.changeset/six-crabs-itch.md
index 5a49f35cd9..49eb2c240f 100644
--- a/.changeset/six-crabs-itch.md
+++ b/.changeset/six-crabs-itch.md
@@ -12,7 +12,6 @@ Before
import {
Arbitrary,
AST,
- Equivalence,
FastCheck,
JSONSchema,
ParseResult,
@@ -27,7 +26,6 @@ After
import {
Arbitrary,
SchemaAST, // changed
- SchemaEquivalence, // changed
FastCheck,
JSONSchema,
ParseResult,
@@ -55,3 +53,23 @@ import { ArrayFormatter, TreeFormatter } from "effect/ParseResult"
### Serializable
Merged into `Schema` module.
+
+### Equivalence
+
+Merged into `Schema` module.
+
+Before
+
+```ts
+import { Equivalence } from "@effect/schema"
+
+Equivalence.make(myschema)
+```
+
+After
+
+```ts
+import { Schema } from "@effect/schema"
+
+Schema.equivalence(myschema)
+```
diff --git a/packages/effect/src/Arbitrary.ts b/packages/effect/src/Arbitrary.ts
index 6d0ccbc7d3..5f98b93f26 100644
--- a/packages/effect/src/Arbitrary.ts
+++ b/packages/effect/src/Arbitrary.ts
@@ -57,7 +57,7 @@ export const makeLazy = (schema: Schema.Schema): LazyArbitrary
*/
export const make = (schema: Schema.Schema): FastCheck.Arbitrary => makeLazy(schema)(FastCheck)
-const getAnnotation = AST.getAnnotation>(AST.ArbitraryAnnotationId)
+const getArbitraryAnnotation = AST.getAnnotation>(AST.ArbitraryAnnotationId)
const getRefinementFromArbitrary = (
ast: AST.Refinement,
@@ -113,7 +113,7 @@ const go = (
ctx: Context,
path: ReadonlyArray
): LazyArbitrary => {
- const hook = getAnnotation(ast)
+ const hook = getArbitraryAnnotation(ast)
if (Option.isSome(hook)) {
switch (ast._tag) {
case "Declaration":
diff --git a/packages/effect/src/Pretty.ts b/packages/effect/src/Pretty.ts
index c769b8437e..c301c0c938 100644
--- a/packages/effect/src/Pretty.ts
+++ b/packages/effect/src/Pretty.ts
@@ -31,10 +31,10 @@ export type PrettyAnnotation = read
*/
export const make = (schema: Schema.Schema): (a: A) => string => compile(schema.ast, [])
-const getAnnotation = AST.getAnnotation>(AST.PrettyAnnotationId)
+const getPrettyAnnotation = AST.getAnnotation>(AST.PrettyAnnotationId)
const getMatcher = (defaultPretty: Pretty) => (ast: AST.AST): Pretty =>
- Option.match(getAnnotation(ast), {
+ Option.match(getPrettyAnnotation(ast), {
onNone: () => defaultPretty,
onSome: (handler) => handler()
})
@@ -50,7 +50,7 @@ const formatUnknown = getMatcher(util_.formatUnknown)
*/
export const match: AST.Match> = {
"Declaration": (ast, go, path) => {
- const annotation = getAnnotation(ast)
+ const annotation = getPrettyAnnotation(ast)
if (Option.isSome(annotation)) {
return annotation.value(...ast.typeParameters.map((tp) => go(tp, path)))
}
@@ -78,7 +78,7 @@ export const match: AST.Match> = {
"BigIntKeyword": getMatcher((a) => `${String(a)}n`),
"Enums": stringify,
"TupleType": (ast, go, path) => {
- const hook = getAnnotation(ast)
+ const hook = getPrettyAnnotation(ast)
if (Option.isSome(hook)) {
return hook.value()
}
@@ -120,7 +120,7 @@ export const match: AST.Match> = {
}
},
"TypeLiteral": (ast, go, path) => {
- const hook = getAnnotation(ast)
+ const hook = getPrettyAnnotation(ast)
if (Option.isSome(hook)) {
return hook.value()
}
@@ -165,7 +165,7 @@ export const match: AST.Match> = {
}
},
"Union": (ast, go, path) => {
- const hook = getAnnotation(ast)
+ const hook = getPrettyAnnotation(ast)
if (Option.isSome(hook)) {
return hook.value()
}
@@ -179,7 +179,7 @@ export const match: AST.Match> = {
}
},
"Suspend": (ast, go, path) => {
- return Option.match(getAnnotation(ast), {
+ return Option.match(getPrettyAnnotation(ast), {
onNone: () => {
const get = util_.memoizeThunk(() => go(ast.f(), path))
return (a) => get()(a)
@@ -188,13 +188,13 @@ export const match: AST.Match> = {
})
},
"Refinement": (ast, go, path) => {
- return Option.match(getAnnotation(ast), {
+ return Option.match(getPrettyAnnotation(ast), {
onNone: () => go(ast.from, path),
onSome: (handler) => handler()
})
},
"Transformation": (ast, go, path) => {
- return Option.match(getAnnotation(ast), {
+ return Option.match(getPrettyAnnotation(ast), {
onNone: () => go(ast.to, path),
onSome: (handler) => handler()
})
diff --git a/packages/effect/src/Schema.ts b/packages/effect/src/Schema.ts
index 1301778a74..512cd08b52 100644
--- a/packages/effect/src/Schema.ts
+++ b/packages/effect/src/Schema.ts
@@ -45,7 +45,6 @@ import * as redacted_ from "./Redacted.js"
import * as Request from "./Request.js"
import type { ParseOptions } from "./SchemaAST.js"
import * as AST from "./SchemaAST.js"
-import type * as equivalence_ from "./SchemaEquivalence.js"
import * as sortedSet_ from "./SortedSet.js"
import * as string_ from "./String.js"
import * as struct_ from "./Struct.js"
@@ -3869,7 +3868,7 @@ export declare namespace Annotations {
readonly jsonSchema?: AST.JSONSchemaAnnotation
readonly arbitrary?: ArbitraryAnnotation
readonly pretty?: pretty_.PrettyAnnotation
- readonly equivalence?: equivalence_.EquivalenceAnnotation
+ readonly equivalence?: AST.EquivalenceAnnotation
readonly concurrency?: AST.ConcurrencyAnnotation
readonly batching?: AST.BatchingAnnotation
readonly parseIssueTitle?: AST.ParseIssueTitleAnnotation
@@ -9655,3 +9654,191 @@ export const TaggedRequest =
}
} as any
}
+
+// -------------------------------------------------------------------------------------------------
+// Equivalence compiler
+// -------------------------------------------------------------------------------------------------
+
+/**
+ * Given a schema `Schema`, returns an `Equivalence` instance for `A`.
+ *
+ * @category Equivalence
+ * @since 3.10.0
+ */
+export const equivalence = (schema: Schema): Equivalence.Equivalence => go(schema.ast, [])
+
+const getEquivalenceAnnotation = AST.getAnnotation>(AST.EquivalenceAnnotationId)
+
+const go = (ast: AST.AST, path: ReadonlyArray): Equivalence.Equivalence => {
+ const hook = getEquivalenceAnnotation(ast)
+ if (option_.isSome(hook)) {
+ switch (ast._tag) {
+ case "Declaration":
+ return hook.value(...ast.typeParameters.map((tp) => go(tp, path)))
+ case "Refinement":
+ return hook.value(go(ast.from, path))
+ default:
+ return hook.value()
+ }
+ }
+ switch (ast._tag) {
+ case "NeverKeyword":
+ throw new Error(errors_.getEquivalenceUnsupportedErrorMessage(ast, path))
+ case "Transformation":
+ return go(ast.to, path)
+ case "Declaration":
+ case "Literal":
+ case "StringKeyword":
+ case "TemplateLiteral":
+ case "UniqueSymbol":
+ case "SymbolKeyword":
+ case "UnknownKeyword":
+ case "AnyKeyword":
+ case "NumberKeyword":
+ case "BooleanKeyword":
+ case "BigIntKeyword":
+ case "UndefinedKeyword":
+ case "VoidKeyword":
+ case "Enums":
+ case "ObjectKeyword":
+ return Equal.equals
+ case "Refinement":
+ return go(ast.from, path)
+ case "Suspend": {
+ const get = util_.memoizeThunk(() => go(ast.f(), path))
+ return (a, b) => get()(a, b)
+ }
+ case "TupleType": {
+ const elements = ast.elements.map((element, i) => go(element.type, path.concat(i)))
+ const rest = ast.rest.map((annotatedAST) => go(annotatedAST.type, path))
+ return Equivalence.make((a, b) => {
+ const len = a.length
+ if (len !== b.length) {
+ return false
+ }
+ // ---------------------------------------------
+ // handle elements
+ // ---------------------------------------------
+ let i = 0
+ for (; i < Math.min(len, ast.elements.length); i++) {
+ if (!elements[i](a[i], b[i])) {
+ return false
+ }
+ }
+ // ---------------------------------------------
+ // handle rest element
+ // ---------------------------------------------
+ if (array_.isNonEmptyReadonlyArray(rest)) {
+ const [head, ...tail] = rest
+ for (; i < len - tail.length; i++) {
+ if (!head(a[i], b[i])) {
+ return false
+ }
+ }
+ // ---------------------------------------------
+ // handle post rest elements
+ // ---------------------------------------------
+ for (let j = 0; j < tail.length; j++) {
+ i += j
+ if (!tail[j](a[i], b[i])) {
+ return false
+ }
+ }
+ }
+ return true
+ })
+ }
+ case "TypeLiteral": {
+ if (ast.propertySignatures.length === 0 && ast.indexSignatures.length === 0) {
+ return Equal.equals
+ }
+ const propertySignatures = ast.propertySignatures.map((ps) => go(ps.type, path.concat(ps.name)))
+ const indexSignatures = ast.indexSignatures.map((is) => go(is.type, path))
+ return Equivalence.make((a, b) => {
+ const aStringKeys = Object.keys(a)
+ const aSymbolKeys = Object.getOwnPropertySymbols(a)
+ // ---------------------------------------------
+ // handle property signatures
+ // ---------------------------------------------
+ for (let i = 0; i < propertySignatures.length; i++) {
+ const ps = ast.propertySignatures[i]
+ const name = ps.name
+ const aHas = Object.prototype.hasOwnProperty.call(a, name)
+ const bHas = Object.prototype.hasOwnProperty.call(b, name)
+ if (ps.isOptional) {
+ if (aHas !== bHas) {
+ return false
+ }
+ }
+ if (aHas && bHas && !propertySignatures[i](a[name], b[name])) {
+ return false
+ }
+ }
+ // ---------------------------------------------
+ // handle index signatures
+ // ---------------------------------------------
+ let bSymbolKeys: Array | undefined
+ let bStringKeys: Array | undefined
+ for (let i = 0; i < indexSignatures.length; i++) {
+ const is = ast.indexSignatures[i]
+ const base = AST.getParameterBase(is.parameter)
+ const isSymbol = AST.isSymbolKeyword(base)
+ if (isSymbol) {
+ bSymbolKeys = bSymbolKeys || Object.getOwnPropertySymbols(b)
+ if (aSymbolKeys.length !== bSymbolKeys.length) {
+ return false
+ }
+ } else {
+ bStringKeys = bStringKeys || Object.keys(b)
+ if (aStringKeys.length !== bStringKeys.length) {
+ return false
+ }
+ }
+ const aKeys = isSymbol ? aSymbolKeys : aStringKeys
+ for (let j = 0; j < aKeys.length; j++) {
+ const key = aKeys[j]
+ if (
+ !Object.prototype.hasOwnProperty.call(b, key) || !indexSignatures[i](a[key], b[key])
+ ) {
+ return false
+ }
+ }
+ }
+ return true
+ })
+ }
+ case "Union": {
+ const searchTree = ParseResult.getSearchTree(ast.types, true)
+ const ownKeys = util_.ownKeys(searchTree.keys)
+ const len = ownKeys.length
+ return Equivalence.make((a, b) => {
+ let candidates: Array = []
+ if (len > 0 && Predicate.isRecord(a)) {
+ for (let i = 0; i < len; i++) {
+ const name = ownKeys[i]
+ const buckets = searchTree.keys[name].buckets
+ if (Object.prototype.hasOwnProperty.call(a, name)) {
+ const literal = String(a[name])
+ if (Object.prototype.hasOwnProperty.call(buckets, literal)) {
+ candidates = candidates.concat(buckets[literal])
+ }
+ }
+ }
+ }
+ if (searchTree.otherwise.length > 0) {
+ candidates = candidates.concat(searchTree.otherwise)
+ }
+ const tuples = candidates.map((ast) => [go(ast, path), ParseResult.is({ ast } as any)] as const)
+ for (let i = 0; i < tuples.length; i++) {
+ const [equivalence, is] = tuples[i]
+ if (is(a) && is(b)) {
+ if (equivalence(a, b)) {
+ return true
+ }
+ }
+ }
+ return false
+ })
+ }
+ }
+}
diff --git a/packages/effect/src/SchemaAST.ts b/packages/effect/src/SchemaAST.ts
index d4d0b041e4..ddd8679a06 100644
--- a/packages/effect/src/SchemaAST.ts
+++ b/packages/effect/src/SchemaAST.ts
@@ -4,6 +4,7 @@
import * as Arr from "./Array.js"
import type { Effect } from "./Effect.js"
+import type { Equivalence } from "./Equivalence.js"
import { dual, identity } from "./Function.js"
import { globalValue } from "./GlobalValue.js"
import * as errors_ from "./internal/schema/errors.js"
@@ -185,6 +186,14 @@ export const ArbitraryAnnotationId: unique symbol = Symbol.for("effect/annotatio
*/
export const PrettyAnnotationId: unique symbol = Symbol.for("effect/annotation/Pretty")
+/**
+ * @category annotations
+ * @since 3.10.0
+ */
+export type EquivalenceAnnotation = readonly []> = (
+ ...equivalences: { readonly [K in keyof TypeParameters]: Equivalence }
+) => Equivalence
+
/**
* @category annotations
* @since 3.10.0
diff --git a/packages/effect/src/SchemaEquivalence.ts b/packages/effect/src/SchemaEquivalence.ts
deleted file mode 100644
index 2dbbcdee89..0000000000
--- a/packages/effect/src/SchemaEquivalence.ts
+++ /dev/null
@@ -1,204 +0,0 @@
-/**
- * @since 3.10.0
- */
-
-import * as Arr from "./Array.js"
-import * as Equal from "./Equal.js"
-import * as Equivalence from "./Equivalence.js"
-import * as errors_ from "./internal/schema/errors.js"
-import * as util_ from "./internal/schema/util.js"
-import * as Option from "./Option.js"
-import * as ParseResult from "./ParseResult.js"
-import * as Predicate from "./Predicate.js"
-import type * as Schema from "./Schema.js"
-import * as AST from "./SchemaAST.js"
-
-/**
- * @category annotations
- * @since 3.10.0
- */
-export type EquivalenceAnnotation = readonly []> = (
- ...equivalences: { readonly [K in keyof TypeParameters]: Equivalence.Equivalence }
-) => Equivalence.Equivalence
-
-/**
- * @category Equivalence
- * @since 3.10.0
- */
-export const make = (schema: Schema.Schema): Equivalence.Equivalence => go(schema.ast, [])
-
-const getAnnotation = AST.getAnnotation>(AST.EquivalenceAnnotationId)
-
-const go = (ast: AST.AST, path: ReadonlyArray): Equivalence.Equivalence => {
- const hook = getAnnotation(ast)
- if (Option.isSome(hook)) {
- switch (ast._tag) {
- case "Declaration":
- return hook.value(...ast.typeParameters.map((tp) => go(tp, path)))
- case "Refinement":
- return hook.value(go(ast.from, path))
- default:
- return hook.value()
- }
- }
- switch (ast._tag) {
- case "NeverKeyword":
- throw new Error(errors_.getEquivalenceUnsupportedErrorMessage(ast, path))
- case "Transformation":
- return go(ast.to, path)
- case "Declaration":
- case "Literal":
- case "StringKeyword":
- case "TemplateLiteral":
- case "UniqueSymbol":
- case "SymbolKeyword":
- case "UnknownKeyword":
- case "AnyKeyword":
- case "NumberKeyword":
- case "BooleanKeyword":
- case "BigIntKeyword":
- case "UndefinedKeyword":
- case "VoidKeyword":
- case "Enums":
- case "ObjectKeyword":
- return Equal.equals
- case "Refinement":
- return go(ast.from, path)
- case "Suspend": {
- const get = util_.memoizeThunk(() => go(ast.f(), path))
- return (a, b) => get()(a, b)
- }
- case "TupleType": {
- const elements = ast.elements.map((element, i) => go(element.type, path.concat(i)))
- const rest = ast.rest.map((annotatedAST) => go(annotatedAST.type, path))
- return Equivalence.make((a, b) => {
- const len = a.length
- if (len !== b.length) {
- return false
- }
- // ---------------------------------------------
- // handle elements
- // ---------------------------------------------
- let i = 0
- for (; i < Math.min(len, ast.elements.length); i++) {
- if (!elements[i](a[i], b[i])) {
- return false
- }
- }
- // ---------------------------------------------
- // handle rest element
- // ---------------------------------------------
- if (Arr.isNonEmptyReadonlyArray(rest)) {
- const [head, ...tail] = rest
- for (; i < len - tail.length; i++) {
- if (!head(a[i], b[i])) {
- return false
- }
- }
- // ---------------------------------------------
- // handle post rest elements
- // ---------------------------------------------
- for (let j = 0; j < tail.length; j++) {
- i += j
- if (!tail[j](a[i], b[i])) {
- return false
- }
- }
- }
- return true
- })
- }
- case "TypeLiteral": {
- if (ast.propertySignatures.length === 0 && ast.indexSignatures.length === 0) {
- return Equal.equals
- }
- const propertySignatures = ast.propertySignatures.map((ps) => go(ps.type, path.concat(ps.name)))
- const indexSignatures = ast.indexSignatures.map((is) => go(is.type, path))
- return Equivalence.make((a, b) => {
- const aStringKeys = Object.keys(a)
- const aSymbolKeys = Object.getOwnPropertySymbols(a)
- // ---------------------------------------------
- // handle property signatures
- // ---------------------------------------------
- for (let i = 0; i < propertySignatures.length; i++) {
- const ps = ast.propertySignatures[i]
- const name = ps.name
- const aHas = Object.prototype.hasOwnProperty.call(a, name)
- const bHas = Object.prototype.hasOwnProperty.call(b, name)
- if (ps.isOptional) {
- if (aHas !== bHas) {
- return false
- }
- }
- if (aHas && bHas && !propertySignatures[i](a[name], b[name])) {
- return false
- }
- }
- // ---------------------------------------------
- // handle index signatures
- // ---------------------------------------------
- let bSymbolKeys: Array | undefined
- let bStringKeys: Array | undefined
- for (let i = 0; i < indexSignatures.length; i++) {
- const is = ast.indexSignatures[i]
- const base = AST.getParameterBase(is.parameter)
- const isSymbol = AST.isSymbolKeyword(base)
- if (isSymbol) {
- bSymbolKeys = bSymbolKeys || Object.getOwnPropertySymbols(b)
- if (aSymbolKeys.length !== bSymbolKeys.length) {
- return false
- }
- } else {
- bStringKeys = bStringKeys || Object.keys(b)
- if (aStringKeys.length !== bStringKeys.length) {
- return false
- }
- }
- const aKeys = isSymbol ? aSymbolKeys : aStringKeys
- for (let j = 0; j < aKeys.length; j++) {
- const key = aKeys[j]
- if (
- !Object.prototype.hasOwnProperty.call(b, key) || !indexSignatures[i](a[key], b[key])
- ) {
- return false
- }
- }
- }
- return true
- })
- }
- case "Union": {
- const searchTree = ParseResult.getSearchTree(ast.types, true)
- const ownKeys = util_.ownKeys(searchTree.keys)
- const len = ownKeys.length
- return Equivalence.make((a, b) => {
- let candidates: Array = []
- if (len > 0 && Predicate.isRecord(a)) {
- for (let i = 0; i < len; i++) {
- const name = ownKeys[i]
- const buckets = searchTree.keys[name].buckets
- if (Object.prototype.hasOwnProperty.call(a, name)) {
- const literal = String(a[name])
- if (Object.prototype.hasOwnProperty.call(buckets, literal)) {
- candidates = candidates.concat(buckets[literal])
- }
- }
- }
- }
- if (searchTree.otherwise.length > 0) {
- candidates = candidates.concat(searchTree.otherwise)
- }
- const tuples = candidates.map((ast) => [go(ast, path), ParseResult.is({ ast } as any)] as const)
- for (let i = 0; i < tuples.length; i++) {
- const [equivalence, is] = tuples[i]
- if (is(a) && is(b)) {
- if (equivalence(a, b)) {
- return true
- }
- }
- }
- return false
- })
- }
- }
-}
diff --git a/packages/effect/src/index.ts b/packages/effect/src/index.ts
index e38dc4864f..52f1a01328 100644
--- a/packages/effect/src/index.ts
+++ b/packages/effect/src/index.ts
@@ -770,11 +770,6 @@ export * as Schema from "./Schema.js"
*/
export * as SchemaAST from "./SchemaAST.js"
-/**
- * @since 3.10.0
- */
-export * as SchemaEquivalence from "./SchemaEquivalence.js"
-
/**
* @since 2.0.0
*/
diff --git a/packages/effect/test/Schema/Schema/BigDecimal/BigDecimalFromSelf.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/BigDecimalFromSelf.test.ts
index 9092297cbd..81967aac85 100644
--- a/packages/effect/test/Schema/Schema/BigDecimal/BigDecimalFromSelf.test.ts
+++ b/packages/effect/test/Schema/Schema/BigDecimal/BigDecimalFromSelf.test.ts
@@ -1,7 +1,6 @@
import { BigDecimal } from "effect"
import * as Pretty from "effect/Pretty"
import * as S from "effect/Schema"
-import * as Equivalence from "effect/SchemaEquivalence"
import * as Util from "effect/test/Schema/TestUtils"
import { describe, expect, it } from "vitest"
@@ -43,7 +42,7 @@ describe("BigDecimalFromSelf", () => {
it("equivalence", () => {
const schema = S.BigDecimalFromSelf
- const equivalence = Equivalence.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(BigDecimal.fromNumber(1), BigDecimal.unsafeFromString("1"))).toBe(true)
expect(equivalence(BigDecimal.fromNumber(2), BigDecimal.unsafeFromString("1"))).toBe(false)
diff --git a/packages/effect/test/Schema/Schema/Chunk/NonEmptyChunkFromSelf.test.ts b/packages/effect/test/Schema/Schema/Chunk/NonEmptyChunkFromSelf.test.ts
index 8b3d7b1018..620dff6f5e 100644
--- a/packages/effect/test/Schema/Schema/Chunk/NonEmptyChunkFromSelf.test.ts
+++ b/packages/effect/test/Schema/Schema/Chunk/NonEmptyChunkFromSelf.test.ts
@@ -3,7 +3,6 @@ import * as C from "effect/Chunk"
import * as FastCheck from "effect/FastCheck"
import * as Pretty from "effect/Pretty"
import * as S from "effect/Schema"
-import * as Equivalence from "effect/SchemaEquivalence"
import * as Util from "effect/test/Schema/TestUtils"
import { describe, expect, it } from "vitest"
@@ -64,7 +63,7 @@ describe("NonEmptyChunkFromSelf", () => {
it("equivalence", () => {
const schema = S.NonEmptyChunkFromSelf(S.String)
- const equivalence = Equivalence.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(C.make("a", "b"), C.make("a", "b"))).toEqual(true)
expect(equivalence(C.make("a", "b"), C.make("a", "c"))).toEqual(false)
expect(equivalence(C.make("a", "b"), C.make("a"))).toEqual(false)
diff --git a/packages/effect/test/Schema/Schema/Class/TaggedClass.test.ts b/packages/effect/test/Schema/Schema/Class/TaggedClass.test.ts
index f561b3cba3..31f501f903 100644
--- a/packages/effect/test/Schema/Schema/Class/TaggedClass.test.ts
+++ b/packages/effect/test/Schema/Schema/Class/TaggedClass.test.ts
@@ -1,6 +1,5 @@
import { pipe, Struct } from "effect"
import * as S from "effect/Schema"
-import * as Equivalence from "effect/SchemaEquivalence"
import * as Util from "effect/test/Schema/TestUtils"
import { describe, expect, it } from "vitest"
@@ -153,7 +152,7 @@ details: Duplicate key "_tag"`)
class A extends S.TaggedClass()("A", {
a: S.String
}) {}
- const eqA = Equivalence.make(A)
+ const eqA = S.equivalence(A)
expect(eqA(new A({ a: "a" }), new A({ a: "a" }))).toBe(true)
expect(eqA(new A({ a: "a" }), new A({ a: "b" }))).toBe(false)
@@ -161,7 +160,7 @@ details: Duplicate key "_tag"`)
b: S.Number,
as: S.Array(A)
}) {}
- const eqB = Equivalence.make(B)
+ const eqB = S.equivalence(B)
expect(eqB(new B({ b: 1, as: [] }), new B({ b: 1, as: [] }))).toBe(true)
expect(eqB(new B({ b: 1, as: [] }), new B({ b: 2, as: [] }))).toBe(false)
expect(eqB(new B({ b: 1, as: [new A({ a: "a" })] }), new B({ b: 1, as: [new A({ a: "a" })] }))).toBe(true)
diff --git a/packages/effect/test/Schema/Schema/SortedSet/SortedSetFromSelf.test.ts b/packages/effect/test/Schema/Schema/SortedSet/SortedSetFromSelf.test.ts
index 61ec5447e6..bdb84b5ac1 100644
--- a/packages/effect/test/Schema/Schema/SortedSet/SortedSetFromSelf.test.ts
+++ b/packages/effect/test/Schema/Schema/SortedSet/SortedSetFromSelf.test.ts
@@ -2,7 +2,6 @@ import * as N from "effect/Number"
import * as P from "effect/ParseResult"
import * as Pretty from "effect/Pretty"
import * as Schema from "effect/Schema"
-import * as Equivalence from "effect/SchemaEquivalence"
import * as SortedSet from "effect/SortedSet"
import * as S from "effect/String"
import * as Util from "effect/test/Schema/TestUtils"
@@ -79,7 +78,7 @@ describe("SortedSetFromSelf", () => {
it("equivalence", () => {
const schema = Schema.SortedSetFromSelf(Schema.String, S.Order, S.Order)
- const eq = Equivalence.make(schema)
+ const eq = Schema.equivalence(schema)
const a = SortedSet.fromIterable([] as Array, S.Order)
const b = SortedSet.fromIterable(["a"] as Array, S.Order)
diff --git a/packages/effect/test/Schema/SchemaEquivalence.test.ts b/packages/effect/test/Schema/Schema/equivalence.test.ts
similarity index 91%
rename from packages/effect/test/Schema/SchemaEquivalence.test.ts
rename to packages/effect/test/Schema/Schema/equivalence.test.ts
index c372e21e76..9da821514a 100644
--- a/packages/effect/test/Schema/SchemaEquivalence.test.ts
+++ b/packages/effect/test/Schema/Schema/equivalence.test.ts
@@ -8,7 +8,6 @@ import * as Hash from "effect/Hash"
import * as Option from "effect/Option"
import { isUnknown } from "effect/Predicate"
import * as S from "effect/Schema"
-import * as E from "effect/SchemaEquivalence"
import * as fc from "fast-check"
import { describe, expect, it } from "vitest"
@@ -21,7 +20,7 @@ export const propertyType = (
) => {
const arb = A.makeLazy(schema)(fc)
// console.log(fc.sample(arb, 10))
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
const reflexivity = fc.property(arb, (a) => equivalence(a, a))
const symmetry = fc.property(arb, arb, (a, b) => equivalence(a, b) === equivalence(b, a))
@@ -73,13 +72,13 @@ const MySymbol = S.SymbolFromSelf.annotations({
describe("SchemaEquivalence", () => {
it("the errors should disply a path", () => {
- expect(() => E.make(S.Tuple(S.Never as any))).toThrow(
+ expect(() => S.equivalence(S.Tuple(S.Never as any))).toThrow(
new Error(`Unsupported schema
at path: [0]
details: Cannot build an Equivalence
schema (NeverKeyword): never`)
)
- expect(() => E.make(S.Struct({ a: S.Never as any }))).toThrow(
+ expect(() => S.equivalence(S.Struct({ a: S.Never as any }))).toThrow(
new Error(`Unsupported schema
at path: ["a"]
details: Cannot build an Equivalence
@@ -89,16 +88,16 @@ schema (NeverKeyword): never`)
it("transformation", () => {
const schema = S.NumberFromString
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(1, 1)).toBe(true)
expect(equivalence(1, 2)).toBe(false)
})
- it("E.make(S.encodedSchema(schema))", () => {
+ it("S.equivalence(S.encodedSchema(schema))", () => {
const schema = S.NumberFromString
- const equivalence = E.make(S.encodedSchema(schema))
+ const equivalence = S.equivalence(S.encodedSchema(schema))
expect(equivalence("a", "a")).toBe(true)
@@ -106,7 +105,7 @@ schema (NeverKeyword): never`)
})
it("never", () => {
- expect(() => E.make(S.Never)).toThrow(
+ expect(() => S.equivalence(S.Never)).toThrow(
new Error(`Unsupported schema
details: Cannot build an Equivalence
schema (NeverKeyword): never`)
@@ -115,7 +114,7 @@ schema (NeverKeyword): never`)
it("string", () => {
const schema = MyString
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence("a", "a")).toBe(true)
@@ -126,7 +125,7 @@ schema (NeverKeyword): never`)
it("Refinement", () => {
const schema = S.NonEmptyString
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence("a", "a")).toBe(true)
@@ -138,7 +137,7 @@ schema (NeverKeyword): never`)
describe("declaration", () => {
it("should return Equal.equals when an annotation doesn't exist", () => {
const schema = S.declare(isUnknown)
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence).toStrictEqual(Equal.equals)
const make = (id: number, s: string) => {
@@ -161,7 +160,7 @@ schema (NeverKeyword): never`)
it("Chunk", () => {
const schema = S.ChunkFromSelf(MyNumber)
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(Chunk.empty(), Chunk.empty())).toBe(true)
expect(equivalence(Chunk.make(1, 2, 3), Chunk.make(1, 2, 3))).toBe(true)
@@ -174,7 +173,7 @@ schema (NeverKeyword): never`)
it("Date", () => {
const schema = S.DateFromSelf
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
const now = new Date()
expect(equivalence(now, now)).toBe(true)
@@ -187,7 +186,7 @@ schema (NeverKeyword): never`)
it("Data", () => {
const schema = S.DataFromSelf(S.Struct({ a: MyString, b: MyNumber }))
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(Data.struct({ a: "ok", b: 0 }), Data.struct({ a: "ok", b: 0 }))).toBe(true)
@@ -196,7 +195,7 @@ schema (NeverKeyword): never`)
it("Either", () => {
const schema = S.EitherFromSelf({ left: MyString, right: MyNumber })
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(Either.right(1), Either.right(1))).toBe(true)
expect(equivalence(Either.left("a"), Either.left("a"))).toBe(true)
@@ -209,7 +208,7 @@ schema (NeverKeyword): never`)
it("Option", () => {
const schema = S.OptionFromSelf(MyNumber)
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(Option.none(), Option.none())).toBe(true)
expect(equivalence(Option.some(1), Option.some(1))).toBe(true)
@@ -221,7 +220,7 @@ schema (NeverKeyword): never`)
it("ReadonlySet", () => {
const schema = S.ReadonlySetFromSelf(MyNumber)
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(new Set(), new Set())).toBe(true)
expect(equivalence(new Set([1, 2, 3]), new Set([1, 2, 3]))).toBe(true)
@@ -233,7 +232,7 @@ schema (NeverKeyword): never`)
it("ReadonlyMap", () => {
const schema = S.ReadonlyMapFromSelf({ key: MyString, value: MyNumber })
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(new Map(), new Map())).toBe(true)
expect(equivalence(new Map([["a", 1], ["b", 2]]), new Map([["a", 1], ["b", 2]]))).toBe(true)
@@ -246,7 +245,7 @@ schema (NeverKeyword): never`)
it("Uint8Array", () => {
const schema = S.Uint8ArrayFromSelf
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(new Uint8Array(), new Uint8Array())).toBe(true)
expect(
@@ -264,7 +263,7 @@ schema (NeverKeyword): never`)
const schema = S.instanceOf(URL, {
equivalence: () => Equivalence.make((a, b) => a.href === b.href)
})
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(new URL("https://example.com/page"), new URL("https://example.com/page")))
.toBe(true)
@@ -277,7 +276,7 @@ schema (NeverKeyword): never`)
describe("union", () => {
it("primitives", () => {
const schema = S.Union(MyString, MyNumber)
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence("a", "a")).toBe(true)
expect(equivalence(1, 1)).toBe(true)
@@ -292,7 +291,7 @@ schema (NeverKeyword): never`)
const a = S.Struct({ a: MyString })
const ab = S.Struct({ a: MyString, b: S.Number })
const schema = S.Union(a, ab)
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence({ a: "a", b: 1 }, { a: "a", b: 1 })).toBe(true)
expect(equivalence({ a: "a", b: 1 }, { a: "a", b: 2 })).toBe(true)
@@ -307,7 +306,7 @@ schema (NeverKeyword): never`)
S.Struct({ tag: S.Literal("a"), a: MyString }),
S.Struct({ tag: S.Literal("b"), b: S.Number })
)
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence({ tag: "a", a: "a" }, { tag: "a", a: "a" })).toBe(true)
expect(equivalence({ tag: "b", b: 1 }, { tag: "b", b: 1 })).toBe(true)
@@ -321,14 +320,14 @@ schema (NeverKeyword): never`)
describe("tuple", () => {
it("empty", () => {
const schema = S.Tuple()
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence([], [])).toBe(true)
})
it("e", () => {
const schema = S.Tuple(MyString, MyNumber)
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(["a", 1], ["a", 1])).toBe(true)
@@ -340,7 +339,7 @@ schema (NeverKeyword): never`)
it("e r", () => {
const schema = S.Tuple([S.String], S.Number)
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(["a"], ["a"])).toBe(true)
expect(equivalence(["a", 1], ["a", 1])).toBe(true)
@@ -354,7 +353,7 @@ schema (NeverKeyword): never`)
it("r", () => {
const schema = S.Array(MyNumber)
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence([], [])).toBe(true)
expect(equivalence([1], [1])).toBe(true)
@@ -368,7 +367,7 @@ schema (NeverKeyword): never`)
it("r e", () => {
const schema = S.Tuple([], MyString, MyNumber)
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence([1], [1])).toBe(true)
expect(equivalence(["a", 1], ["a", 1])).toBe(true)
@@ -384,7 +383,7 @@ schema (NeverKeyword): never`)
describe("optional element support", () => {
it("e?", () => {
const schema = S.Tuple(S.optionalElement(MyString))
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence([], [])).toBe(true)
expect(equivalence(["a"], ["a"])).toBe(true)
@@ -398,7 +397,7 @@ schema (NeverKeyword): never`)
it("e? e?", () => {
const schema = S.Tuple(S.optionalElement(MyString), S.optionalElement(MyNumber))
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence([], [])).toBe(true)
expect(equivalence(["a"], ["a"])).toBe(true)
@@ -416,7 +415,7 @@ schema (NeverKeyword): never`)
it("e e?", () => {
const schema = S.Tuple(MyString, S.optionalElement(MyNumber))
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence(["a"], ["a"])).toBe(true)
expect(equivalence(["a", 1], ["a", 1])).toBe(true)
@@ -430,7 +429,7 @@ schema (NeverKeyword): never`)
it("e? r", () => {
const schema = S.Tuple([S.optionalElement(S.String)], S.Number)
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence([], [])).toBe(true)
expect(equivalence(["a"], ["a"])).toBe(true)
@@ -449,14 +448,14 @@ schema (NeverKeyword): never`)
describe("struct", () => {
it("empty", () => {
const schema = S.Struct({})
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence({}, {})).toBe(false)
})
it("string keys", () => {
const schema = S.Struct({ a: MyString, b: MyNumber })
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence({ a: "a", b: 1 }, { a: "a", b: 1 })).toBe(true)
// should ignore excess properties
@@ -479,7 +478,7 @@ schema (NeverKeyword): never`)
const a = Symbol.for("effect/Schema/test/a")
const b = Symbol.for("effect/Schema/test/b")
const schema = S.Struct({ [a]: MyString, [b]: MyNumber })
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence({ [a]: "a", [b]: 1 }, { [a]: "a", [b]: 1 })).toBe(true)
// should ignore excess properties
@@ -503,7 +502,7 @@ schema (NeverKeyword): never`)
a: S.optionalWith(MyString, { exact: true }),
b: S.optionalWith(S.Union(MyNumber, S.Undefined), { exact: true })
})
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence({ a: "a", b: 1 }, { a: "a", b: 1 })).toBe(true)
expect(equivalence({ b: 1 }, { b: 1 })).toBe(true)
@@ -525,7 +524,7 @@ schema (NeverKeyword): never`)
describe("record", () => {
it("record(never, number)", () => {
const schema = S.Record({ key: S.Never, value: MyNumber })
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
const input = {}
expect(equivalence(input, input)).toBe(true)
@@ -534,7 +533,7 @@ schema (NeverKeyword): never`)
it("record(string, number)", () => {
const schema = S.Record({ key: MyString, value: MyNumber })
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence({}, {})).toBe(true)
expect(equivalence({ a: 1 }, { a: 1 })).toBe(true)
@@ -553,7 +552,7 @@ schema (NeverKeyword): never`)
it("record(symbol, number)", () => {
const schema = S.Record({ key: MySymbol, value: MyNumber })
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
const a = Symbol.for("effect/Schema/test/a")
const b = Symbol.for("effect/Schema/test/b")
@@ -574,7 +573,7 @@ schema (NeverKeyword): never`)
it("struct record", () => {
const schema = S.Struct({ a: MyString, b: MyString }, S.Record({ key: MyString, value: MyString }))
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence({ a: "a", b: "b" }, { a: "a", b: "b" })).toBe(true)
expect(equivalence({ a: "a", b: "b", c: "c" }, { a: "a", b: "b", c: "c" })).toBe(true)
@@ -590,7 +589,7 @@ schema (NeverKeyword): never`)
const schema = S.Struct({ a: MyString, b: MyString }).annotations({
equivalence: () => Equivalence.make((x, y) => x.a === y.a)
})
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
expect(equivalence({ a: "a", b: "b" }, { a: "a", b: "b" })).toBe(true)
expect(equivalence({ a: "a", b: "b" }, { a: "a", b: "c" })).toBe(true)
@@ -612,7 +611,7 @@ schema (NeverKeyword): never`)
as: S.Array(S.suspend((): S.Schema => schema))
})
- const equivalence = E.make(schema)
+ const equivalence = S.equivalence(schema)
const a1: A = { a: "a1", as: [] }
expect(equivalence(a1, a1)).toBe(true)
@@ -653,7 +652,7 @@ schema (NeverKeyword): never`)
right: Expression
})
- const equivalence = E.make(Operation)
+ const equivalence = S.equivalence(Operation)
const a1: Operation = {
type: "operation",
@@ -712,7 +711,7 @@ schema (NeverKeyword): never`)
describe("should handle annotations", () => {
const expectHook = (source: S.Schema) => {
const schema = source.annotations({ equivalence: () => () => true })
- const eq = E.make(schema)
+ const eq = S.equivalence(schema)
expect(eq("a" as any, "b" as any)).toEqual(true)
}
diff --git a/packages/schema/src/Equivalence.ts b/packages/schema/src/Equivalence.ts
deleted file mode 100644
index edffa47537..0000000000
--- a/packages/schema/src/Equivalence.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * @since 0.67.0
- */
-
-/**
- * @category re-exports
- * @since 0.76.0
- */
-export * from "effect/SchemaEquivalence"
diff --git a/packages/schema/src/index.ts b/packages/schema/src/index.ts
index 1c2004c88d..53259a4d3c 100644
--- a/packages/schema/src/index.ts
+++ b/packages/schema/src/index.ts
@@ -8,11 +8,6 @@ export * as AST from "./AST.js"
*/
export * as Arbitrary from "./Arbitrary.js"
-/**
- * @since 0.67.0
- */
-export * as Equivalence from "./Equivalence.js"
-
/**
* @since 0.67.0
*/