@soundscript/soundscript 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +1 -1
  2. package/async.d.ts +3 -3
  3. package/async.js +2 -2
  4. package/async.js.map +1 -1
  5. package/codec.d.ts +3 -2
  6. package/codec.js +2 -2
  7. package/codec.js.map +1 -1
  8. package/compare.js +5 -10
  9. package/compare.js.map +1 -1
  10. package/decode.d.ts +6 -4
  11. package/decode.js +5 -5
  12. package/decode.js.map +1 -1
  13. package/derive.d.ts +6 -0
  14. package/derive.js +8 -0
  15. package/derive.js.map +1 -0
  16. package/encode.d.ts +11 -9
  17. package/encode.js +5 -5
  18. package/encode.js.map +1 -1
  19. package/experimental/thunk.js.map +1 -0
  20. package/fetch.d.ts +1 -1
  21. package/hash.js +9 -14
  22. package/hash.js.map +1 -1
  23. package/json.d.ts +29 -2
  24. package/json.js +124 -1
  25. package/json.js.map +1 -1
  26. package/numerics.d.ts +523 -0
  27. package/numerics.js +1357 -0
  28. package/numerics.js.map +1 -0
  29. package/package.json +94 -35
  30. package/result.d.ts +21 -5
  31. package/result.js +55 -19
  32. package/result.js.map +1 -1
  33. package/soundscript/async.sts +7 -7
  34. package/soundscript/codec.sts +8 -7
  35. package/soundscript/compare.sts +5 -13
  36. package/soundscript/decode.sts +15 -13
  37. package/soundscript/derive.sts +7 -0
  38. package/soundscript/encode.sts +18 -16
  39. package/soundscript/hash.sts +9 -17
  40. package/soundscript/json.sts +209 -3
  41. package/soundscript/numerics.sts +1937 -0
  42. package/soundscript/result.sts +93 -24
  43. package/soundscript/typeclasses.sts +22 -16
  44. package/soundscript/value.sts +133 -0
  45. package/typeclasses.d.ts +2 -2
  46. package/typeclasses.js +10 -9
  47. package/typeclasses.js.map +1 -1
  48. package/value.d.ts +9 -0
  49. package/value.js +105 -0
  50. package/value.js.map +1 -0
  51. package/experimental/component.d.ts +0 -40
  52. package/experimental/component.js +0 -46
  53. package/experimental/component.js.map +0 -1
  54. package/soundscript/experimental/component.sts +0 -69
  55. package/thunk.js.map +0 -1
  56. /package/{thunk.d.ts → experimental/thunk.d.ts} +0 -0
  57. /package/{thunk.js → experimental/thunk.js} +0 -0
  58. /package/soundscript/{thunk.sts → experimental/thunk.sts} +0 -0
package/result.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"result.js","sourceRoot":"","sources":["./soundscript/result.sts"],"names":[],"mappings":"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","sourcesContent":["import { normalizeThrown } from '@soundscript/soundscript/failures';\nimport { type Bind, type Kind, type Kind2, type TypeLambda } from '@soundscript/soundscript/hkt';\nimport { type Applicative, type Functor, type Monad } from '@soundscript/soundscript/typeclasses';\n\n// #[variance(T: out)]\nexport type Ok<T> = { readonly tag: 'ok'; readonly value: T };\n// #[variance(E: out)]\nexport type Err<E> = { readonly tag: 'err'; readonly error: E };\n\n// #[variance(T: out, E: out)]\nexport type Result<T, E> = Ok<T> | Err<E>;\n// #[variance(T: out)]\nexport type Some<T> = Ok<T>;\nexport type None = Err<void>;\n// #[variance(T: out)]\nexport type Option<T> = Result<T, void>;\n\nexport interface OptionF extends TypeLambda {\n readonly type: Option<this['Args'][0]>;\n}\n\nexport interface ResultF extends TypeLambda {\n readonly type: Result<this['Args'][1], this['Args'][0]>;\n}\n\nexport type OptionKind<T> = Kind<OptionF, T>;\nexport type ResultKind<E, T> = Kind2<ResultF, E, T>;\n\nexport function ok<T>(value: T): Result<T, never> {\n return { tag: 'ok', value };\n}\n\nexport function err(): Result<never, void>;\nexport function err<E>(error: E): Result<never, E>;\nexport function err<E>(error?: E): Result<never, E | void> {\n return { tag: 'err', error };\n}\n\nexport function some<T>(value: T): Option<T> {\n return ok(value);\n}\n\nexport function none(): Option<never> {\n return err();\n}\n\nexport function isOk<T, E>(value: Result<T, E>): value is Ok<T> {\n return value.tag === 'ok';\n}\n\nexport function isErr<T, E>(value: Result<T, E>): value is Err<E> {\n return value.tag === 'err';\n}\n\nexport function isSome<T>(value: Option<T>): value is Some<T> {\n return isOk(value);\n}\n\nexport function isNone<T>(value: Option<T>): value is None {\n return isErr(value);\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return (typeof value === 'object' || typeof value === 'function') &&\n value !== null &&\n 'then' in value &&\n typeof value.then === 'function';\n}\n\nexport function resultOf<T>(fn: () => Promise<T>): Promise<Result<T, Error>>;\nexport function resultOf<T, E>(\n fn: () => Promise<T>,\n mapError: (error: Error) => E,\n): Promise<Result<T, E>>;\nexport function resultOf<T>(fn: () => T): Result<T, Error>;\nexport function resultOf<T, E>(fn: () => T, mapError: (error: Error) => E): Result<T, E>;\nexport function resultOf<T, E>(\n fn: () => T | Promise<T>,\n mapError?: (error: Error) => E,\n): Result<T, E | Error> | Promise<Result<T, E | Error>> {\n try {\n const value = fn();\n if (isPromiseLike(value)) {\n return Promise.resolve(value as PromiseLike<T>).then(\n (resolved) => ok(resolved),\n (error) => {\n const normalized = normalizeThrown(error);\n return err(mapError ? mapError(normalized) : normalized);\n },\n );\n }\n return ok(value);\n } catch (error) {\n const normalized = normalizeThrown(error);\n return err(mapError ? mapError(normalized) : normalized);\n }\n}\n\nfunction mapOption<A, B>(value: Option<A>, f: (value: A) => B): Option<B> {\n return isOk(value) ? ok(f(value.value)) : value;\n}\n\nfunction apOption<A, B>(\n fn: Option<(value: A) => B>,\n value: Option<A>,\n): Option<B> {\n if (!isOk(fn)) {\n return fn;\n }\n return isOk(value) ? ok(fn.value(value.value)) : value;\n}\n\nfunction flatMapOption<A, B>(value: Option<A>, f: (value: A) => Option<B>): Option<B> {\n return isOk(value) ? f(value.value) : value;\n}\n\nconst optionMonadImpl: Monad<OptionF> = {\n ap: apOption,\n flatMap: flatMapOption,\n map: mapOption,\n pure: some,\n};\n\nexport const optionFunctor: Functor<OptionF> = optionMonadImpl;\nexport const optionApplicative: Applicative<OptionF> = optionMonadImpl;\nexport const optionMonad: Monad<OptionF> = optionMonadImpl;\n\nfunction mapResult<E, A, B>(value: Result<A, E>, f: (value: A) => B): Result<B, E> {\n return isOk(value) ? ok(f(value.value)) : value;\n}\n\nfunction apResult<E, A, B>(\n fn: Result<(value: A) => B, E>,\n value: Result<A, E>,\n): Result<B, E> {\n if (!isOk(fn)) {\n return fn;\n }\n return isOk(value) ? ok(fn.value(value.value)) : value;\n}\n\nfunction flatMapResult<E, A, B>(\n value: Result<A, E>,\n f: (value: A) => Result<B, E>,\n): Result<B, E> {\n return isOk(value) ? f(value.value) : value;\n}\n\nfunction createResultMonad<E>(): Monad<Bind<ResultF, [E]>> {\n return {\n ap: apResult,\n flatMap: flatMapResult,\n map: mapResult,\n pure: ok,\n };\n}\n\nexport function resultFunctor<E>(): Functor<Bind<ResultF, [E]>> {\n return createResultMonad<E>();\n}\n\nexport function resultApplicative<E>(): Applicative<Bind<ResultF, [E]>> {\n return createResultMonad<E>();\n}\n\nexport function resultMonad<E>(): Monad<Bind<ResultF, [E]>> {\n return createResultMonad<E>();\n}\n\nfunction macroRuntimeError(name: string): never {\n throw new Error(\n `${name}(...) is a Soundscript macro and should be removed during Soundscript expansion.`,\n );\n}\n\nexport function Try<T, E>(value: Result<T, E>): T;\nexport function Try(_value: unknown): never {\n return macroRuntimeError('Try');\n}\n"]}
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["./soundscript/result.sts"],"names":[],"mappings":"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","sourcesContent":["import { normalizeThrown } from '@soundscript/soundscript/failures';\nimport { type Bind, type Kind, type Kind2, type TypeLambda } from '@soundscript/soundscript/hkt';\nimport { type Applicative, type Functor, type Monad } from '@soundscript/soundscript/typeclasses';\nimport {\n __valueFactory,\n __valueKey,\n __valueReadonly,\n __valueShallowToken,\n} from '@soundscript/soundscript/value';\n\nconst makeOk = __valueFactory<Ok<unknown>, [unknown]>(\n (value) => __valueKey('ok', __valueShallowToken(value)),\n () => Object.create(Ok.prototype) as Ok<unknown>,\n (instance, value) => {\n __valueReadonly(instance, 'tag', 'ok');\n __valueReadonly(instance, 'value', value);\n },\n);\n\nconst makeErr = __valueFactory<Err<unknown>, [unknown]>(\n (error) => __valueKey('err', __valueShallowToken(error)),\n () => Object.create(Err.prototype) as Err<unknown>,\n (instance, error) => {\n __valueReadonly(instance, 'tag', 'err');\n __valueReadonly(instance, 'error', error);\n },\n);\n\nconst makeSome = __valueFactory<Some<unknown>, [unknown]>(\n (value) => __valueKey('some', __valueShallowToken(value)),\n () => Object.create(Some.prototype) as Some<unknown>,\n (instance, value) => {\n __valueReadonly(instance, 'tag', 'some');\n __valueReadonly(instance, 'value', value);\n },\n);\n\nconst makeNone = __valueFactory<None, []>(\n () => __valueKey('none'),\n () => Object.create(None.prototype) as None,\n (instance) => {\n __valueReadonly(instance, 'tag', 'none');\n },\n);\n\n// #[variance(T: out)]\nexport class Ok<T> {\n readonly tag!: 'ok';\n readonly value!: T;\n\n constructor(value: T) {\n return makeOk(value) as Ok<T>;\n }\n}\n\n// #[variance(E: out)]\nexport class Err<E> {\n readonly tag!: 'err';\n readonly error!: E;\n\n constructor(error: E) {\n return makeErr(error) as Err<E>;\n }\n}\n\n// #[variance(T: out, E: out)]\nexport type Result<T, E> = Ok<T> | Err<E>;\n\n// #[variance(T: out)]\nexport class Some<T> {\n readonly tag!: 'some';\n readonly value!: T;\n\n constructor(value: T) {\n return makeSome(value) as Some<T>;\n }\n}\n\nexport class None {\n readonly tag!: 'none';\n\n constructor() {\n return makeNone();\n }\n}\n\n// #[variance(T: out)]\nexport type Option<T> = Some<T> | None;\n\nexport interface OptionF extends TypeLambda {\n readonly type: Option<this['Args'][0]>;\n}\n\nexport interface ResultF extends TypeLambda {\n readonly type: Result<this['Args'][1], this['Args'][0]>;\n}\n\nexport type OptionKind<T> = Kind<OptionF, T>;\nexport type ResultKind<E, T> = Kind2<ResultF, E, T>;\n\nexport function ok<T>(value: T): Result<T, never> {\n return new Ok(value);\n}\n\nexport function err(): Result<never, void>;\nexport function err<E>(error: E): Result<never, E>;\nexport function err<E>(error?: E): Result<never, E | void> {\n return new Err(error);\n}\n\nexport function some<T>(value: T): Option<T> {\n return new Some(value);\n}\n\nexport function none(): Option<never> {\n return new None();\n}\n\nexport function isOk<T, E>(value: Result<T, E>): value is Ok<T> {\n return value instanceof Ok;\n}\n\nexport function isErr<T, E>(value: Result<T, E>): value is Err<E> {\n return value instanceof Err;\n}\n\nexport function isSome<T>(value: Option<T>): value is Some<T> {\n return value instanceof Some;\n}\n\nexport function isNone<T>(value: Option<T>): value is None {\n return value instanceof None;\n}\n\nfunction isPromiseInstance<T>(value: unknown): value is Promise<T> {\n return value instanceof Promise;\n}\n\nexport function resultOf<T>(fn: () => Promise<T>): Promise<Result<T, Error>>;\nexport function resultOf<T, E>(\n fn: () => Promise<T>,\n mapError: (error: Error) => E,\n): Promise<Result<T, E>>;\nexport function resultOf<T>(fn: () => T): Result<T, Error>;\nexport function resultOf<T, E>(fn: () => T, mapError: (error: Error) => E): Result<T, E>;\nexport function resultOf<T, E>(\n fn: () => T | Promise<T>,\n mapError?: (error: Error) => E,\n): Result<T, E | Error> | Promise<Result<T, E | Error>> {\n try {\n const value = fn();\n if (isPromiseInstance<T>(value)) {\n return value.then(\n (resolved) => ok(resolved),\n (error) => {\n const normalized = normalizeThrown(error);\n return err(mapError ? mapError(normalized) : normalized);\n },\n );\n }\n return ok(value);\n } catch (error) {\n const normalized = normalizeThrown(error);\n return err(mapError ? mapError(normalized) : normalized);\n }\n}\n\nfunction mapOption<A, B>(value: Option<A>, f: (value: A) => B): Option<B> {\n return isSome(value) ? some(f(value.value)) : value;\n}\n\nfunction apOption<A, B>(\n fn: Option<(value: A) => B>,\n value: Option<A>,\n): Option<B> {\n if (!isSome(fn)) {\n return fn;\n }\n return isSome(value) ? some(fn.value(value.value)) : value;\n}\n\nfunction flatMapOption<A, B>(value: Option<A>, f: (value: A) => Option<B>): Option<B> {\n return isSome(value) ? f(value.value) : value;\n}\n\nconst optionMonadImpl: Monad<OptionF> = {\n ap: apOption,\n flatMap: flatMapOption,\n map: mapOption,\n pure: some,\n};\n\nexport const optionFunctor: Functor<OptionF> = optionMonadImpl;\nexport const optionApplicative: Applicative<OptionF> = optionMonadImpl;\nexport const optionMonad: Monad<OptionF> = optionMonadImpl;\n\nfunction mapResult<E, A, B>(value: Result<A, E>, f: (value: A) => B): Result<B, E> {\n return isOk(value) ? ok(f(value.value)) : value;\n}\n\nfunction apResult<E, A, B>(\n fn: Result<(value: A) => B, E>,\n value: Result<A, E>,\n): Result<B, E> {\n if (!isOk(fn)) {\n return fn;\n }\n return isOk(value) ? ok(fn.value(value.value)) : value;\n}\n\nfunction flatMapResult<E, A, B>(\n value: Result<A, E>,\n f: (value: A) => Result<B, E>,\n): Result<B, E> {\n return isOk(value) ? f(value.value) : value;\n}\n\nfunction createResultMonad<E>(): Monad<Bind<ResultF, [E]>> {\n return {\n ap: apResult,\n flatMap: flatMapResult,\n map: mapResult,\n pure: ok,\n };\n}\n\nexport function resultFunctor<E>(): Functor<Bind<ResultF, [E]>> {\n return createResultMonad<E>();\n}\n\nexport function resultApplicative<E>(): Applicative<Bind<ResultF, [E]>> {\n return createResultMonad<E>();\n}\n\nexport function resultMonad<E>(): Monad<Bind<ResultF, [E]>> {\n return createResultMonad<E>();\n}\n\nfunction macroRuntimeError(name: string): never {\n throw new Error(\n `${name}(...) is a Soundscript macro and should be removed during Soundscript expansion.`,\n );\n}\n\nexport function Try<T, E>(value: Result<T, E>): T;\nexport function Try(_value: unknown): never {\n return macroRuntimeError('Try');\n}\n"]}
@@ -109,7 +109,7 @@ export function flatMap<A, B, E1, E2>(
109
109
 
110
110
  export function recover<A, B, E>(
111
111
  task: Task<A, E>,
112
- project: (error: E) => B | PromiseLike<B>,
112
+ project: (error: E) => B | Promise<B>,
113
113
  ): Task<A | B, Error> {
114
114
  return async (signal?: AbortSignalLike) => {
115
115
  const result = await task(signal);
@@ -123,7 +123,7 @@ export function recover<A, B, E>(
123
123
 
124
124
  export function tap<A, E>(
125
125
  task: Task<A, E>,
126
- effect: (value: A) => unknown | PromiseLike<unknown>,
126
+ effect: (value: A) => unknown | Promise<unknown>,
127
127
  ): Task<A, E | Error> {
128
128
  return async (signal?: AbortSignalLike) => {
129
129
  const result = await task(signal);
@@ -138,7 +138,7 @@ export function tap<A, E>(
138
138
 
139
139
  export function tapError<A, E>(
140
140
  task: Task<A, E>,
141
- effect: (error: E) => unknown | PromiseLike<unknown>,
141
+ effect: (error: E) => unknown | Promise<unknown>,
142
142
  ): Task<A, E | Error> {
143
143
  return async (signal?: AbortSignalLike) => {
144
144
  const result = await task(signal);
@@ -276,8 +276,8 @@ export function taskAsyncMonad<E>(): AsyncMonad<Bind<TaskF, [E]>> {
276
276
  const monad = createTaskMonad<E>();
277
277
  return {
278
278
  ...monad,
279
- fromPromise<A>(promise: PromiseLike<A>): Task<A, E> {
280
- return fromPromise(() => Promise.resolve(promise)) as Task<A, E>;
279
+ fromPromise<A>(promise: Promise<A>): Task<A, E> {
280
+ return fromPromise(() => promise) as Task<A, E>;
281
281
  },
282
282
  };
283
283
  }
@@ -309,7 +309,7 @@ export const promiseMonad: Monad<PromiseF> = {
309
309
 
310
310
  export const promiseAsyncMonad: AsyncMonad<PromiseF> = {
311
311
  ...promiseMonad,
312
- fromPromise<A>(promise: PromiseLike<A>): Promise<A> {
313
- return Promise.resolve(promise);
312
+ fromPromise<A>(promise: Promise<A>): Promise<A> {
313
+ return promise;
314
314
  },
315
315
  };
@@ -15,7 +15,7 @@ import {
15
15
  stringEncoder as stringEncoderValue,
16
16
  } from '@soundscript/soundscript/encode';
17
17
  import type { Invariant } from '@soundscript/soundscript/typeclasses';
18
- import { ok } from '@soundscript/soundscript/result';
18
+ import { isErr, ok, type Result } from '@soundscript/soundscript/result';
19
19
 
20
20
  export type { EncodeFailure, Encoder } from '@soundscript/soundscript/encode';
21
21
  export {
@@ -25,8 +25,9 @@ export {
25
25
  stringEncoderValue as stringEncoder,
26
26
  };
27
27
 
28
- export interface Codec<T, TEncoded = unknown, DE = DecodeFailure, EE = EncodeFailure>
29
- extends Decoder<T, DE>, Encoder<T, TEncoded, EE> {}
28
+ // #[variance(T: inout, TEncoded: out, DE: out, EE: out)]
29
+ export type Codec<T, TEncoded = unknown, DE = DecodeFailure, EE = EncodeFailure> =
30
+ Decoder<T, DE> & Encoder<T, TEncoded, EE>;
30
31
 
31
32
  export interface CodecF extends TypeLambda {
32
33
  readonly type: Codec<this['Args'][3], this['Args'][2], this['Args'][1], this['Args'][0]>;
@@ -37,10 +38,10 @@ export function codec<T, TEncoded, DE, EE>(
37
38
  encoder: Encoder<T, TEncoded, EE>,
38
39
  ): Codec<T, TEncoded, DE, EE> {
39
40
  return {
40
- decode(value) {
41
+ decode(value): Result<T, DE> {
41
42
  return decoder.decode(value);
42
43
  },
43
- encode(value) {
44
+ encode(value): Result<TEncoded, EE> {
44
45
  return encoder.encode(value);
45
46
  },
46
47
  };
@@ -53,9 +54,9 @@ export function imap<A, B, TEncoded, DE, EE>(
53
54
  ): Codec<B, TEncoded, DE, EE> {
54
55
  return codec(
55
56
  {
56
- decode(value) {
57
+ decode(value): Result<B, DE> {
57
58
  const decoded = base.decode(value);
58
- return decoded.tag === 'err' ? decoded : ok(decodeMap(decoded.value));
59
+ return isErr(decoded) ? decoded : ok(decodeMap(decoded.value));
59
60
  },
60
61
  },
61
62
  contramapEncoder(base, encodeMap),
@@ -1,4 +1,4 @@
1
- import type { Option, Result } from '@soundscript/soundscript/result';
1
+ import { isErr, isNone, isOk, isSome, type Option, type Result } from '@soundscript/soundscript/result';
2
2
 
3
3
  export type Ordering = -1 | 0 | 1;
4
4
 
@@ -91,15 +91,11 @@ export function tupleEq<const TEqs extends readonly Eq<unknown>[]>(
91
91
  export function optionEq<T>(itemEq: Eq<T>): Eq<Option<T>> {
92
92
  return {
93
93
  equals(left, right) {
94
- if (left.tag !== right.tag) {
95
- return false;
96
- }
97
-
98
- if (left.tag === 'ok' && right.tag === 'ok') {
94
+ if (isSome(left) && isSome(right)) {
99
95
  return itemEq.equals(left.value, right.value);
100
96
  }
101
97
 
102
- return true;
98
+ return isNone(left) && isNone(right);
103
99
  },
104
100
  };
105
101
  }
@@ -107,15 +103,11 @@ export function optionEq<T>(itemEq: Eq<T>): Eq<Option<T>> {
107
103
  export function resultEq<T, E>(okEq: Eq<T>, errEq: Eq<E>): Eq<Result<T, E>> {
108
104
  return {
109
105
  equals(left, right) {
110
- if (left.tag !== right.tag) {
111
- return false;
112
- }
113
-
114
- if (left.tag === 'ok' && right.tag === 'ok') {
106
+ if (isOk(left) && isOk(right)) {
115
107
  return okEq.equals(left.value, right.value);
116
108
  }
117
109
 
118
- if (left.tag === 'err' && right.tag === 'err') {
110
+ if (isErr(left) && isErr(right)) {
119
111
  return errEq.equals(left.error, right.error);
120
112
  }
121
113
 
@@ -1,5 +1,5 @@
1
1
  import { type ErrorFrame, Failure } from '@soundscript/soundscript/failures';
2
- import { err, isErr, ok, type Option, type Result } from '@soundscript/soundscript/result';
2
+ import { err, isErr, none, ok, some, type Option, type Result } from '@soundscript/soundscript/result';
3
3
 
4
4
  export type DecodePathSegment = string | number;
5
5
  export type DecodePath = readonly DecodePathSegment[];
@@ -33,14 +33,16 @@ export class DecodeFailure extends Failure {
33
33
  }
34
34
  }
35
35
 
36
- export interface Decoder<T, E = DecodeFailure> {
36
+ // #[variance(T: out, E: out)]
37
+ export type Decoder<T, E = DecodeFailure> = {
37
38
  decode(value: unknown): Result<T, E>;
38
- }
39
+ };
39
40
 
40
- export interface OptionalDecoder<T, E = DecodeFailure> extends Decoder<T | undefined, E> {
41
+ // #[variance(T: out, E: out)]
42
+ export type OptionalDecoder<T, E = DecodeFailure> = Decoder<T | undefined, E> & {
41
43
  readonly __soundscriptOptional: true;
42
44
  readonly inner: Decoder<T, E>;
43
- }
45
+ };
44
46
 
45
47
  type DecoderValue<TDecoder> = TDecoder extends Decoder<infer TValue, unknown> ? TValue : never;
46
48
  type DecoderError<TDecoder> = TDecoder extends Decoder<unknown, infer E> ? E : never;
@@ -49,7 +51,7 @@ type ObjectShape = Record<string, Decoder<unknown, unknown>>;
49
51
  type TupleShape = readonly Decoder<unknown, unknown>[];
50
52
 
51
53
  export const string: Decoder<string> = {
52
- decode(value) {
54
+ decode(value): Result<string, DecodeFailure> {
53
55
  return typeof value === 'string'
54
56
  ? ok(value)
55
57
  : err(new DecodeFailure('Expected string.', { cause: value }));
@@ -57,7 +59,7 @@ export const string: Decoder<string> = {
57
59
  };
58
60
 
59
61
  export const number: Decoder<number> = {
60
- decode(value) {
62
+ decode(value): Result<number, DecodeFailure> {
61
63
  return typeof value === 'number'
62
64
  ? ok(value)
63
65
  : err(new DecodeFailure('Expected number.', { cause: value }));
@@ -65,7 +67,7 @@ export const number: Decoder<number> = {
65
67
  };
66
68
 
67
69
  export const boolean: Decoder<boolean> = {
68
- decode(value) {
70
+ decode(value): Result<boolean, DecodeFailure> {
69
71
  return typeof value === 'boolean'
70
72
  ? ok(value)
71
73
  : err(new DecodeFailure('Expected boolean.', { cause: value }));
@@ -73,7 +75,7 @@ export const boolean: Decoder<boolean> = {
73
75
  };
74
76
 
75
77
  export const bigint: Decoder<bigint> = {
76
- decode(value) {
78
+ decode(value): Result<bigint, DecodeFailure> {
77
79
  if (typeof value === 'bigint') {
78
80
  return ok(value);
79
81
  }
@@ -191,16 +193,16 @@ export function option<T, E>(item: Decoder<T, E>): Decoder<Option<T>, E | Decode
191
193
  return union(
192
194
  map(
193
195
  object({
194
- tag: literal('ok'),
196
+ tag: literal('some'),
195
197
  value: item,
196
198
  }),
197
- (value) => ok(value.value) as Option<T>,
199
+ (value) => some(value.value) as Option<T>,
198
200
  ),
199
201
  map(
200
202
  object({
201
- tag: literal('err'),
203
+ tag: literal('none'),
202
204
  }),
203
- () => err() as Option<T>,
205
+ () => none() as Option<T>,
204
206
  ),
205
207
  );
206
208
  }
@@ -0,0 +1,7 @@
1
+ // Macro binding placeholders. The compiler-owned macro pipeline consumes these symbols.
2
+ export const eq: unknown = undefined;
3
+ export const hash: unknown = undefined;
4
+ export const decode: unknown = undefined;
5
+ export const encode: unknown = undefined;
6
+ export const codec: unknown = undefined;
7
+ export const tagged: unknown = undefined;
@@ -1,6 +1,6 @@
1
1
  import { type Bind, type Kind3, type TypeLambda } from '@soundscript/soundscript/hkt';
2
2
  import { Failure } from '@soundscript/soundscript/failures';
3
- import { err, isErr, ok, type Option, type Result } from '@soundscript/soundscript/result';
3
+ import { err, isErr, isOk, isSome, ok, type Option, type Result } from '@soundscript/soundscript/result';
4
4
  import type { Contravariant } from '@soundscript/soundscript/typeclasses';
5
5
 
6
6
  export class EncodeFailure extends Failure {
@@ -9,15 +9,17 @@ export class EncodeFailure extends Failure {
9
9
  }
10
10
  }
11
11
 
12
- export interface Encoder<T, TEncoded = unknown, E = EncodeFailure> {
12
+ // #[variance(T: in, TEncoded: out, E: out)]
13
+ export type Encoder<T, TEncoded = unknown, E = EncodeFailure> = {
13
14
  encode(value: T): Result<TEncoded, E>;
14
- }
15
+ };
15
16
 
16
- export interface OptionalEncoder<T, TEncoded = T, E = EncodeFailure>
17
- extends Encoder<T | undefined, TEncoded | undefined, E> {
18
- readonly __soundscriptOptional: true;
19
- readonly inner: Encoder<T, TEncoded, E>;
20
- }
17
+ // #[variance(T: in, TEncoded: out, E: out)]
18
+ export type OptionalEncoder<T, TEncoded = T, E = EncodeFailure> =
19
+ Encoder<T | undefined, TEncoded | undefined, E> & {
20
+ readonly __soundscriptOptional: true;
21
+ readonly inner: Encoder<T, TEncoded, E>;
22
+ };
21
23
 
22
24
  type EncoderInput<TEncoder> = TEncoder extends Encoder<infer T, unknown, unknown> ? T : never;
23
25
  type EncoderOutput<TEncoder> = TEncoder extends Encoder<unknown, infer TEncoded, unknown> ? TEncoded
@@ -140,26 +142,26 @@ export function option<T, TEncoded, E>(
140
142
  item: Encoder<T, TEncoded, E>,
141
143
  ): Encoder<
142
144
  Option<T>,
143
- { readonly error?: undefined; readonly tag: 'err' } | {
144
- readonly tag: 'ok';
145
+ { readonly tag: 'none' } | {
146
+ readonly tag: 'some';
145
147
  readonly value: TEncoded;
146
148
  },
147
149
  E
148
150
  > {
149
151
  return fromEncode<
150
152
  Option<T>,
151
- { readonly error?: undefined; readonly tag: 'err' } | {
152
- readonly tag: 'ok';
153
+ { readonly tag: 'none' } | {
154
+ readonly tag: 'some';
153
155
  readonly value: TEncoded;
154
156
  },
155
157
  E
156
158
  >((value) => {
157
- if (value.tag === 'ok') {
159
+ if (isSome(value)) {
158
160
  const encoded = item.encode(value.value);
159
- return isErr(encoded) ? encoded : ok({ tag: 'ok', value: encoded.value });
161
+ return isErr(encoded) ? encoded : ok({ tag: 'some', value: encoded.value });
160
162
  }
161
163
 
162
- return ok({ tag: 'err', error: undefined });
164
+ return ok({ tag: 'none' });
163
165
  });
164
166
  }
165
167
 
@@ -182,7 +184,7 @@ export function result<T, EValue, TEncoded, EEncoded, EOk, EErr>(
182
184
  },
183
185
  EOk | EErr
184
186
  >((value) => {
185
- if (value.tag === 'ok') {
187
+ if (isOk(value)) {
186
188
  const encoded = okEncoder.encode(value.value);
187
189
  return isErr(encoded) ? encoded : ok({ tag: 'ok', value: encoded.value });
188
190
  }
@@ -1,5 +1,5 @@
1
1
  import type { Eq } from '@soundscript/soundscript/compare';
2
- import type { Option, Result } from '@soundscript/soundscript/result';
2
+ import { isErr, isNone, isOk, isSome, type Option, type Result } from '@soundscript/soundscript/result';
3
3
 
4
4
  export type HashCode = number;
5
5
 
@@ -97,19 +97,15 @@ export function tupleHash<const THashEqs extends readonly HashEq<unknown>[]>(
97
97
  export function optionHash<T>(itemHash: HashEq<T>): HashEq<Option<T>> {
98
98
  return fromHashEq(
99
99
  (value) =>
100
- value.tag === 'ok'
101
- ? combineHashes(stringHash.hash('ok'), itemHash.hash(value.value))
102
- : stringHash.hash('err'),
100
+ isSome(value)
101
+ ? combineHashes(stringHash.hash('some'), itemHash.hash(value.value))
102
+ : stringHash.hash('none'),
103
103
  (left, right) => {
104
- if (left.tag !== right.tag) {
105
- return false;
106
- }
107
-
108
- if (left.tag === 'ok' && right.tag === 'ok') {
104
+ if (isSome(left) && isSome(right)) {
109
105
  return itemHash.equals(left.value, right.value);
110
106
  }
111
107
 
112
- return true;
108
+ return isNone(left) && isNone(right);
113
109
  },
114
110
  );
115
111
  }
@@ -117,19 +113,15 @@ export function optionHash<T>(itemHash: HashEq<T>): HashEq<Option<T>> {
117
113
  export function resultHash<T, E>(okHash: HashEq<T>, errHash: HashEq<E>): HashEq<Result<T, E>> {
118
114
  return fromHashEq(
119
115
  (value) =>
120
- value.tag === 'ok'
116
+ isOk(value)
121
117
  ? combineHashes(stringHash.hash('ok'), okHash.hash(value.value))
122
118
  : combineHashes(stringHash.hash('err'), errHash.hash(value.error)),
123
119
  (left, right) => {
124
- if (left.tag !== right.tag) {
125
- return false;
126
- }
127
-
128
- if (left.tag === 'ok' && right.tag === 'ok') {
120
+ if (isOk(left) && isOk(right)) {
129
121
  return okHash.equals(left.value, right.value);
130
122
  }
131
123
 
132
- if (left.tag === 'err' && right.tag === 'err') {
124
+ if (isErr(left) && isErr(right)) {
133
125
  return errHash.equals(left.error, right.error);
134
126
  }
135
127
 
@@ -2,6 +2,22 @@ import type { Decoder } from '@soundscript/soundscript/decode';
2
2
  import type { Encoder } from '@soundscript/soundscript/encode';
3
3
  import { Failure } from '@soundscript/soundscript/failures';
4
4
  import { isErr, type Result, resultOf } from '@soundscript/soundscript/result';
5
+ import {
6
+ F32,
7
+ F64,
8
+ format as formatNumeric,
9
+ I8,
10
+ I16,
11
+ I32,
12
+ I64,
13
+ isNumeric,
14
+ toHostNumber,
15
+ type Numeric,
16
+ U8,
17
+ U16,
18
+ U32,
19
+ U64,
20
+ } from './numerics.js';
5
21
 
6
22
  export type JsonArray = JsonValue[];
7
23
  export type JsonObject = {
@@ -35,8 +51,26 @@ export type JsonLikeValue =
35
51
  | JsonLikeObject
36
52
  | JsonLikeArray;
37
53
 
54
+ export type MachineJsonArray = MachineJsonLikeValue[];
55
+ export type MachineJsonObject = {
56
+ [key: string]: MachineJsonLikeValue;
57
+ };
58
+ export type MachineJsonLikeValue =
59
+ | string
60
+ | number
61
+ | boolean
62
+ | bigint
63
+ | null
64
+ | undefined
65
+ | Numeric
66
+ | MachineJsonObject
67
+ | MachineJsonArray;
68
+
69
+ export type MachineJsonNumericMode = 'tagged' | 'decimal-string' | 'json-number';
70
+
38
71
  export interface JsonParseOptions {
39
72
  int64?: 'default' | 'lossless';
73
+ numerics?: 'tagged';
40
74
  }
41
75
 
42
76
  export type JsonStringifyBigintMode = 'number' | 'reject' | 'string';
@@ -44,6 +78,7 @@ export type JsonStringifyBigintMode = 'number' | 'reject' | 'string';
44
78
  export interface JsonStringifyOptions {
45
79
  int64?: 'default' | 'string' | 'lossless';
46
80
  readonly bigint?: JsonStringifyBigintMode;
81
+ numerics?: MachineJsonNumericMode;
47
82
  }
48
83
 
49
84
  const MAX_SAFE_INTEGER_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
@@ -66,12 +101,21 @@ export function parseJson(
66
101
  text: string,
67
102
  options: JsonParseOptions & { int64: 'lossless' },
68
103
  ): Result<LosslessJsonValue, JsonParseFailure>;
104
+ export function parseJson(
105
+ text: string,
106
+ options: JsonParseOptions & { numerics: 'tagged' },
107
+ ): Result<MachineJsonLikeValue, JsonParseFailure>;
69
108
  export function parseJson(
70
109
  text: string,
71
110
  options: JsonParseOptions = {},
72
- ): Result<JsonValue | LosslessJsonValue, JsonParseFailure> {
111
+ ): Result<JsonValue | LosslessJsonValue | MachineJsonLikeValue, JsonParseFailure> {
73
112
  return resultOf(
74
- () => options.int64 === 'lossless' ? parseLosslessJson(text) : JSON.parse(text),
113
+ () => {
114
+ const parsed = options.int64 === 'lossless' ? parseLosslessJson(text) : JSON.parse(text);
115
+ return options.numerics === 'tagged'
116
+ ? decodeTaggedMachineJsonValue(parsed as JsonValue | LosslessJsonValue)
117
+ : parsed;
118
+ },
75
119
  (cause) => new JsonParseFailure(cause),
76
120
  );
77
121
  }
@@ -82,11 +126,34 @@ export function stringifyJson(
82
126
  options: JsonStringifyOptions & { int64: 'string' | 'lossless' },
83
127
  ): Result<string, JsonStringifyFailure>;
84
128
  export function stringifyJson(
85
- value: JsonValue | LosslessJsonValue,
129
+ value: MachineJsonLikeValue,
130
+ options: JsonStringifyOptions & { numerics: MachineJsonNumericMode },
131
+ ): Result<string, JsonStringifyFailure>;
132
+ export function stringifyJson(
133
+ value: JsonValue | LosslessJsonValue | MachineJsonLikeValue,
86
134
  options: JsonStringifyOptions = {},
87
135
  ): Result<string, JsonStringifyFailure> {
88
136
  return resultOf(
89
137
  () => {
138
+ if (options.numerics) {
139
+ const normalized = normalizeMachineJsonLikeValue(
140
+ value as MachineJsonLikeValue,
141
+ new Set<object>(),
142
+ options.numerics,
143
+ 'root',
144
+ );
145
+ const encoded = stringifyJsonLikeInternal(
146
+ normalized,
147
+ new Set<object>(),
148
+ options.bigint ?? 'reject',
149
+ 'root',
150
+ );
151
+ if (encoded === undefined) {
152
+ throw new TypeError('JSON stringification produced no top-level value.');
153
+ }
154
+ return encoded;
155
+ }
156
+
90
157
  if (options.int64 === 'string') {
91
158
  return stringifyJsonWithInt64Mode(value as LosslessJsonValue, 'string');
92
159
  }
@@ -322,6 +389,145 @@ function isJsonLikeValueInternal(
322
389
  }
323
390
  }
324
391
 
392
+ function normalizeMachineJsonLikeValue(
393
+ value: MachineJsonLikeValue,
394
+ visited: Set<object>,
395
+ numericMode: MachineJsonNumericMode,
396
+ position: 'array' | 'object' | 'root',
397
+ ): JsonLikeValue {
398
+ if (isNumeric(value)) {
399
+ return normalizeMachineNumericJsonValue(value, numericMode);
400
+ }
401
+
402
+ switch (typeof value) {
403
+ case 'string':
404
+ case 'number':
405
+ case 'boolean':
406
+ case 'bigint':
407
+ return value;
408
+ case 'undefined':
409
+ return position === 'array' ? null : undefined;
410
+ case 'object':
411
+ if (value === null) {
412
+ return null;
413
+ }
414
+
415
+ if (visited.has(value)) {
416
+ throw new TypeError('Converting circular structure to machine JSON text.');
417
+ }
418
+
419
+ visited.add(value);
420
+ try {
421
+ if (Array.isArray(value)) {
422
+ return value.map((entry) =>
423
+ normalizeMachineJsonLikeValue(entry, visited, numericMode, 'array') ?? null
424
+ );
425
+ }
426
+
427
+ const result: Record<string, JsonLikeValue> = {};
428
+ for (const key of Object.keys(value)) {
429
+ const normalized = normalizeMachineJsonLikeValue(
430
+ (value as MachineJsonObject)[key]!,
431
+ visited,
432
+ numericMode,
433
+ 'object',
434
+ );
435
+ if (normalized !== undefined) {
436
+ result[key] = normalized;
437
+ }
438
+ }
439
+ return result;
440
+ } finally {
441
+ visited.delete(value);
442
+ }
443
+ default:
444
+ throw new TypeError(`Unsupported machine JSON value kind: ${typeof value}`);
445
+ }
446
+ }
447
+
448
+ function normalizeMachineNumericJsonValue(
449
+ value: Numeric,
450
+ numericMode: MachineJsonNumericMode,
451
+ ): JsonLikeValue {
452
+ switch (numericMode) {
453
+ case 'tagged':
454
+ return value.toJSON();
455
+ case 'decimal-string':
456
+ return formatNumeric(value);
457
+ case 'json-number':
458
+ switch (value.__soundscript_numeric_kind) {
459
+ case 'i64':
460
+ case 'u64':
461
+ throw new TypeError('json-number machine JSON mode does not support bigint-backed machine numerics.');
462
+ default:
463
+ return toHostNumber(value);
464
+ }
465
+ }
466
+ }
467
+
468
+ function decodeTaggedMachineJsonValue(value: JsonValue | LosslessJsonValue): MachineJsonLikeValue {
469
+ if (Array.isArray(value)) {
470
+ return value.map((entry) => decodeTaggedMachineJsonValue(entry));
471
+ }
472
+
473
+ if (value && typeof value === 'object') {
474
+ const taggedNumeric = decodeTaggedMachineNumeric(value);
475
+ if (taggedNumeric) {
476
+ return taggedNumeric;
477
+ }
478
+
479
+ const result: Record<string, MachineJsonLikeValue> = {};
480
+ for (const key of Object.keys(value)) {
481
+ result[key] = decodeTaggedMachineJsonValue(value[key]!);
482
+ }
483
+ return result;
484
+ }
485
+
486
+ return value;
487
+ }
488
+
489
+ function decodeTaggedMachineNumeric(
490
+ value: Record<string, JsonValue | LosslessJsonValue>,
491
+ ): Numeric | undefined {
492
+ const numericKind = value.$numeric;
493
+ const numericValue = value.value;
494
+ const keys = Object.keys(value);
495
+ if (
496
+ typeof numericKind !== 'string' ||
497
+ typeof numericValue !== 'string' ||
498
+ keys.length !== 2 ||
499
+ !keys.includes('$numeric') ||
500
+ !keys.includes('value')
501
+ ) {
502
+ return undefined;
503
+ }
504
+
505
+ switch (numericKind) {
506
+ case 'f64':
507
+ return F64.parse(numericValue);
508
+ case 'f32':
509
+ return F32.parse(numericValue);
510
+ case 'i8':
511
+ return I8.parse(numericValue);
512
+ case 'i16':
513
+ return I16.parse(numericValue);
514
+ case 'i32':
515
+ return I32.parse(numericValue);
516
+ case 'i64':
517
+ return I64.parse(numericValue);
518
+ case 'u8':
519
+ return U8.parse(numericValue);
520
+ case 'u16':
521
+ return U16.parse(numericValue);
522
+ case 'u32':
523
+ return U32.parse(numericValue);
524
+ case 'u64':
525
+ return U64.parse(numericValue);
526
+ default:
527
+ return undefined;
528
+ }
529
+ }
530
+
325
531
  function stringifyJsonLikeInternal(
326
532
  value: JsonLikeValue,
327
533
  visited: Set<object>,