effect 3.5.8 → 3.6.0

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 (123) hide show
  1. package/DateTime/package.json +6 -0
  2. package/dist/cjs/Context.js.map +1 -1
  3. package/dist/cjs/DateTime.js +1514 -0
  4. package/dist/cjs/DateTime.js.map +1 -0
  5. package/dist/cjs/Effect.js +3 -3
  6. package/dist/cjs/Effect.js.map +1 -1
  7. package/dist/cjs/Either.js +3 -3
  8. package/dist/cjs/List.js.map +1 -1
  9. package/dist/cjs/Metric.js.map +1 -1
  10. package/dist/cjs/Micro.js +93 -41
  11. package/dist/cjs/Micro.js.map +1 -1
  12. package/dist/cjs/Option.js +3 -3
  13. package/dist/cjs/Predicate.js +8 -0
  14. package/dist/cjs/Predicate.js.map +1 -1
  15. package/dist/cjs/Random.js +16 -1
  16. package/dist/cjs/Random.js.map +1 -1
  17. package/dist/cjs/Stream.js +86 -7
  18. package/dist/cjs/Stream.js.map +1 -1
  19. package/dist/cjs/Struct.js +23 -1
  20. package/dist/cjs/Struct.js.map +1 -1
  21. package/dist/cjs/index.js +4 -2
  22. package/dist/cjs/index.js.map +1 -1
  23. package/dist/cjs/internal/configProvider.js.map +1 -1
  24. package/dist/cjs/internal/core.js +1 -1
  25. package/dist/cjs/internal/core.js.map +1 -1
  26. package/dist/cjs/internal/defaultServices.js +9 -2
  27. package/dist/cjs/internal/defaultServices.js.map +1 -1
  28. package/dist/cjs/internal/metric.js.map +1 -1
  29. package/dist/cjs/internal/stream/emit.js +73 -1
  30. package/dist/cjs/internal/stream/emit.js.map +1 -1
  31. package/dist/cjs/internal/stream.js +30 -22
  32. package/dist/cjs/internal/stream.js.map +1 -1
  33. package/dist/cjs/internal/version.js +1 -1
  34. package/dist/dts/ConfigProvider.d.ts +2 -2
  35. package/dist/dts/ConfigProvider.d.ts.map +1 -1
  36. package/dist/dts/Context.d.ts +3 -1
  37. package/dist/dts/Context.d.ts.map +1 -1
  38. package/dist/dts/DateTime.d.ts +1265 -0
  39. package/dist/dts/DateTime.d.ts.map +1 -0
  40. package/dist/dts/Effect.d.ts +18 -4
  41. package/dist/dts/Effect.d.ts.map +1 -1
  42. package/dist/dts/Either.d.ts +4 -4
  43. package/dist/dts/List.d.ts +2 -1
  44. package/dist/dts/List.d.ts.map +1 -1
  45. package/dist/dts/Metric.d.ts +1 -1
  46. package/dist/dts/Metric.d.ts.map +1 -1
  47. package/dist/dts/MetricRegistry.d.ts +1 -1
  48. package/dist/dts/MetricRegistry.d.ts.map +1 -1
  49. package/dist/dts/Micro.d.ts +60 -0
  50. package/dist/dts/Micro.d.ts.map +1 -1
  51. package/dist/dts/Option.d.ts +4 -4
  52. package/dist/dts/Predicate.d.ts +63 -2
  53. package/dist/dts/Predicate.d.ts.map +1 -1
  54. package/dist/dts/Random.d.ts +18 -0
  55. package/dist/dts/Random.d.ts.map +1 -1
  56. package/dist/dts/Stream.d.ts +95 -4
  57. package/dist/dts/Stream.d.ts.map +1 -1
  58. package/dist/dts/StreamEmit.d.ts +44 -0
  59. package/dist/dts/StreamEmit.d.ts.map +1 -1
  60. package/dist/dts/Struct.d.ts +21 -0
  61. package/dist/dts/Struct.d.ts.map +1 -1
  62. package/dist/dts/index.d.ts +4 -0
  63. package/dist/dts/index.d.ts.map +1 -1
  64. package/dist/dts/internal/core.d.ts.map +1 -1
  65. package/dist/dts/internal/defaultServices.d.ts.map +1 -1
  66. package/dist/dts/internal/stream.d.ts.map +1 -1
  67. package/dist/esm/Context.js.map +1 -1
  68. package/dist/esm/DateTime.js +1465 -0
  69. package/dist/esm/DateTime.js.map +1 -0
  70. package/dist/esm/Effect.js +4 -4
  71. package/dist/esm/Effect.js.map +1 -1
  72. package/dist/esm/Either.js +4 -4
  73. package/dist/esm/List.js.map +1 -1
  74. package/dist/esm/Metric.js.map +1 -1
  75. package/dist/esm/Micro.js +88 -38
  76. package/dist/esm/Micro.js.map +1 -1
  77. package/dist/esm/Option.js +4 -4
  78. package/dist/esm/Predicate.js +8 -0
  79. package/dist/esm/Predicate.js.map +1 -1
  80. package/dist/esm/Random.js +15 -0
  81. package/dist/esm/Random.js.map +1 -1
  82. package/dist/esm/Stream.js +84 -5
  83. package/dist/esm/Stream.js.map +1 -1
  84. package/dist/esm/Struct.js +21 -0
  85. package/dist/esm/Struct.js.map +1 -1
  86. package/dist/esm/index.js +4 -0
  87. package/dist/esm/index.js.map +1 -1
  88. package/dist/esm/internal/configProvider.js.map +1 -1
  89. package/dist/esm/internal/core.js +1 -1
  90. package/dist/esm/internal/core.js.map +1 -1
  91. package/dist/esm/internal/defaultServices.js +6 -0
  92. package/dist/esm/internal/defaultServices.js.map +1 -1
  93. package/dist/esm/internal/metric.js.map +1 -1
  94. package/dist/esm/internal/stream/emit.js +71 -0
  95. package/dist/esm/internal/stream/emit.js.map +1 -1
  96. package/dist/esm/internal/stream.js +24 -18
  97. package/dist/esm/internal/stream.js.map +1 -1
  98. package/dist/esm/internal/version.js +1 -1
  99. package/package.json +9 -1
  100. package/src/ConfigProvider.ts +2 -2
  101. package/src/Context.ts +3 -1
  102. package/src/DateTime.ts +2104 -0
  103. package/src/Effect.ts +28 -4
  104. package/src/Either.ts +4 -4
  105. package/src/List.ts +3 -2
  106. package/src/Metric.ts +1 -1
  107. package/src/MetricRegistry.ts +1 -1
  108. package/src/Micro.ts +117 -45
  109. package/src/Option.ts +4 -4
  110. package/src/Predicate.ts +68 -8
  111. package/src/Random.ts +24 -0
  112. package/src/Stream.ts +110 -5
  113. package/src/StreamEmit.ts +53 -0
  114. package/src/Struct.ts +22 -0
  115. package/src/index.ts +5 -0
  116. package/src/internal/configProvider.ts +20 -20
  117. package/src/internal/core.ts +37 -12
  118. package/src/internal/defaultServices.ts +14 -0
  119. package/src/internal/metric/registry.ts +1 -1
  120. package/src/internal/metric.ts +2 -2
  121. package/src/internal/stream/emit.ts +77 -0
  122. package/src/internal/stream.ts +86 -18
  123. package/src/internal/version.ts +1 -1
package/src/Effect.ts CHANGED
@@ -3419,7 +3419,7 @@ export const updateService: {
3419
3419
  // -------------------------------------------------------------------------------------
3420
3420
 
3421
3421
  /**
3422
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
3422
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
3423
3423
  *
3424
3424
  * Here's how the do simulation works:
3425
3425
  *
@@ -3449,7 +3449,7 @@ export const updateService: {
3449
3449
  export const Do: Effect<{}> = effect.Do
3450
3450
 
3451
3451
  /**
3452
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
3452
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
3453
3453
  *
3454
3454
  * Here's how the do simulation works:
3455
3455
  *
@@ -3489,7 +3489,7 @@ export const bind: {
3489
3489
  } = effect.bind
3490
3490
 
3491
3491
  /**
3492
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
3492
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
3493
3493
  *
3494
3494
  * Here's how the do simulation works:
3495
3495
  *
@@ -3535,7 +3535,7 @@ const let_: {
3535
3535
 
3536
3536
  export {
3537
3537
  /**
3538
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
3538
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
3539
3539
  *
3540
3540
  * Here's how the do simulation works:
3541
3541
  *
@@ -4029,6 +4029,12 @@ export const tap: {
4029
4029
  ) => [X] extends [Effect<infer _A1, infer E1, infer R1>] ? Effect<A, E | E1, R | R1>
4030
4030
  : [X] extends [PromiseLike<infer _A1>] ? Effect<A, E | Cause.UnknownException, R>
4031
4031
  : Effect<A, E, R>
4032
+ <A, X, E1, R1>(
4033
+ f: (a: NoInfer<A>) => Effect<X, E1, R1>,
4034
+ options: { onlyEffect: true }
4035
+ ): <E, R>(
4036
+ self: Effect<A, E, R>
4037
+ ) => Effect<A, E | E1, R | R1>
4032
4038
  <X>(
4033
4039
  f: NotFunction<X>
4034
4040
  ): <A, E, R>(
@@ -4036,18 +4042,34 @@ export const tap: {
4036
4042
  ) => [X] extends [Effect<infer _A1, infer E1, infer R1>] ? Effect<A, E | E1, R | R1>
4037
4043
  : [X] extends [PromiseLike<infer _A1>] ? Effect<A, E | Cause.UnknownException, R>
4038
4044
  : Effect<A, E, R>
4045
+ <X, E1, R1>(
4046
+ f: Effect<X, E1, R1>,
4047
+ options: { onlyEffect: true }
4048
+ ): <A, E, R>(
4049
+ self: Effect<A, E, R>
4050
+ ) => Effect<A, E | E1, R | R1>
4039
4051
  <A, E, R, X>(
4040
4052
  self: Effect<A, E, R>,
4041
4053
  f: (a: NoInfer<A>) => X
4042
4054
  ): [X] extends [Effect<infer _A1, infer E1, infer R1>] ? Effect<A, E | E1, R | R1>
4043
4055
  : [X] extends [PromiseLike<infer _A1>] ? Effect<A, E | Cause.UnknownException, R>
4044
4056
  : Effect<A, E, R>
4057
+ <A, E, R, X, E1, R1>(
4058
+ self: Effect<A, E, R>,
4059
+ f: (a: NoInfer<A>) => Effect<X, E1, R1>,
4060
+ options: { onlyEffect: true }
4061
+ ): Effect<A, E | E1, R | R1>
4045
4062
  <A, E, R, X>(
4046
4063
  self: Effect<A, E, R>,
4047
4064
  f: NotFunction<X>
4048
4065
  ): [X] extends [Effect<infer _A1, infer E1, infer R1>] ? Effect<A, E | E1, R | R1>
4049
4066
  : [X] extends [PromiseLike<infer _A1>] ? Effect<A, E | Cause.UnknownException, R>
4050
4067
  : Effect<A, E, R>
4068
+ <A, E, R, X, E1, R1>(
4069
+ self: Effect<A, E, R>,
4070
+ f: Effect<X, E1, R1>,
4071
+ options: { onlyEffect: true }
4072
+ ): Effect<A, E | E1, R | R1>
4051
4073
  } = core.tap
4052
4074
 
4053
4075
  /**
@@ -5958,6 +5980,8 @@ export declare namespace Tag {
5958
5980
  * @category models
5959
5981
  */
5960
5982
  export interface ProhibitedType {
5983
+ Service?: `property "Service" is forbidden`
5984
+ Identifier?: `property "Identifier" is forbidden`
5961
5985
  _op?: `property "_op" is forbidden`
5962
5986
  _tag?: `property "_tag" is forbidden`
5963
5987
  of?: `property "of" is forbidden`
package/src/Either.ts CHANGED
@@ -791,7 +791,7 @@ export const gen: Gen.Gen<EitherTypeLambda, Gen.Adapter<EitherTypeLambda>> = (..
791
791
  // -------------------------------------------------------------------------------------
792
792
 
793
793
  /**
794
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
794
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
795
795
  *
796
796
  * Here's how the do simulation works:
797
797
  *
@@ -821,7 +821,7 @@ export const gen: Gen.Gen<EitherTypeLambda, Gen.Adapter<EitherTypeLambda>> = (..
821
821
  export const Do: Either<{}> = right({})
822
822
 
823
823
  /**
824
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
824
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
825
825
  *
826
826
  * Here's how the do simulation works:
827
827
  *
@@ -861,7 +861,7 @@ export const bind: {
861
861
  } = doNotation.bind<EitherTypeLambda>(map, flatMap)
862
862
 
863
863
  /**
864
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
864
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
865
865
  *
866
866
  * Here's how the do simulation works:
867
867
  *
@@ -907,7 +907,7 @@ const let_: {
907
907
 
908
908
  export {
909
909
  /**
910
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
910
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
911
911
  *
912
912
  * Here's how the do simulation works:
913
913
  *
package/src/List.ts CHANGED
@@ -29,6 +29,7 @@ import * as Equivalence from "./Equivalence.js"
29
29
  import { dual, identity, unsafeCoerce } from "./Function.js"
30
30
  import * as Hash from "./Hash.js"
31
31
  import { format, type Inspectable, NodeInspectSymbol, toJSON } from "./Inspectable.js"
32
+ import type { nonEmpty, NonEmptyIterable } from "./NonEmptyIterable.js"
32
33
  import * as Option from "./Option.js"
33
34
  import type { Pipeable } from "./Pipeable.js"
34
35
  import { pipeArguments } from "./Pipeable.js"
@@ -72,7 +73,7 @@ export interface Nil<out A> extends Iterable<A>, Equal.Equal, Pipeable, Inspecta
72
73
  * @since 2.0.0
73
74
  * @category models
74
75
  */
75
- export interface Cons<out A> extends Iterable<A>, Equal.Equal, Pipeable, Inspectable {
76
+ export interface Cons<out A> extends NonEmptyIterable<A>, Equal.Equal, Pipeable, Inspectable {
76
77
  readonly [TypeId]: TypeId
77
78
  readonly _tag: "Cons"
78
79
  readonly head: A
@@ -96,7 +97,7 @@ export const getEquivalence = <A>(isEquivalent: Equivalence.Equivalence<A>): Equ
96
97
 
97
98
  const _equivalence = getEquivalence(Equal.equals)
98
99
 
99
- const ConsProto: Omit<Cons<unknown>, "head" | "tail"> = {
100
+ const ConsProto: Omit<Cons<unknown>, "head" | "tail" | typeof nonEmpty> = {
100
101
  [TypeId]: TypeId,
101
102
  _tag: "Cons",
102
103
  toString(this: Cons<unknown>) {
package/src/Metric.ts CHANGED
@@ -361,7 +361,7 @@ export const set: {
361
361
  * @since 2.0.0
362
362
  * @category getters
363
363
  */
364
- export const snapshot: Effect.Effect<ReadonlyArray<MetricPair.MetricPair.Untyped>> = internal.snapshot
364
+ export const snapshot: Effect.Effect<Array<MetricPair.MetricPair.Untyped>> = internal.snapshot
365
365
 
366
366
  /**
367
367
  * Creates a metric that ignores input and produces constant output.
@@ -25,7 +25,7 @@ export type MetricRegistryTypeId = typeof MetricRegistryTypeId
25
25
  */
26
26
  export interface MetricRegistry {
27
27
  readonly [MetricRegistryTypeId]: MetricRegistryTypeId
28
- snapshot(): ReadonlyArray<MetricPair.MetricPair.Untyped>
28
+ snapshot(): Array<MetricPair.MetricPair.Untyped>
29
29
  get<Type extends MetricKeyType.MetricKeyType<any, any>>(
30
30
  key: MetricKey.MetricKey<Type>
31
31
  ): MetricHook.MetricHook<
package/src/Micro.ts CHANGED
@@ -562,6 +562,7 @@ export const envUnsafeMakeEmpty = (): Env<never> => {
562
562
  const refs = Object.create(null)
563
563
  refs[currentAbortController.key] = controller
564
564
  refs[currentAbortSignal.key] = controller.signal
565
+ refs[currentScheduler.key] = new MicroSchedulerDefault()
565
566
  return envMake(refs)
566
567
  }
567
568
 
@@ -733,6 +734,79 @@ export const provideServiceEffect: {
733
734
  ): Micro<A, E | E2, Exclude<R, I> | R2> => flatMap(acquire, (service) => provideService(self, tag, service))
734
735
  )
735
736
 
737
+ // ----------------------------------------------------------------------------
738
+ // scheduler
739
+ // ----------------------------------------------------------------------------
740
+
741
+ /**
742
+ * @since 3.5.9
743
+ * @experimental
744
+ * @category scheduler
745
+ */
746
+ export interface MicroScheduler {
747
+ readonly scheduleTask: (task: () => void, priority: number) => void
748
+ readonly shouldYield: (env: Env<unknown>) => boolean
749
+ readonly flush: () => void
750
+ }
751
+
752
+ const setImmediate = "setImmediate" in globalThis ? globalThis.setImmediate : (f: () => void) => setTimeout(f, 0)
753
+
754
+ /**
755
+ * @since 3.5.9
756
+ * @experimental
757
+ * @category scheduler
758
+ */
759
+ export class MicroSchedulerDefault implements MicroScheduler {
760
+ private tasks: Array<() => void> = []
761
+ private running = false
762
+
763
+ /**
764
+ * @since 3.5.9
765
+ */
766
+ scheduleTask(task: () => void, _priority: number) {
767
+ this.tasks.push(task)
768
+ if (!this.running) {
769
+ this.running = true
770
+ setImmediate(this.afterScheduled)
771
+ }
772
+ }
773
+
774
+ /**
775
+ * @since 3.5.9
776
+ */
777
+ afterScheduled = () => {
778
+ this.running = false
779
+ this.runTasks()
780
+ }
781
+
782
+ /**
783
+ * @since 3.5.9
784
+ */
785
+ runTasks() {
786
+ const tasks = this.tasks
787
+ this.tasks = []
788
+ for (let i = 0, len = tasks.length; i < len; i++) {
789
+ tasks[i]()
790
+ }
791
+ }
792
+
793
+ /**
794
+ * @since 3.5.9
795
+ */
796
+ shouldYield(_env: Env<unknown>) {
797
+ return false
798
+ }
799
+
800
+ /**
801
+ * @since 3.5.9
802
+ */
803
+ flush() {
804
+ while (this.tasks.length > 0) {
805
+ this.runTasks()
806
+ }
807
+ }
808
+ }
809
+
736
810
  // ========================================================================
737
811
  // Env refs
738
812
  // ========================================================================
@@ -809,6 +883,16 @@ const currentInterruptible: EnvRef<boolean> = envRefMake(
809
883
  () => true
810
884
  )
811
885
 
886
+ /**
887
+ * @since 3.4.0
888
+ * @experimental
889
+ * @category environment refs
890
+ */
891
+ export const currentScheduler: EnvRef<MicroScheduler> = envRefMake(
892
+ "effect/Micro/currentScheduler",
893
+ () => new MicroSchedulerDefault()
894
+ )
895
+
812
896
  /**
813
897
  * If you have a `Micro` that uses `concurrency: "inherit"`, you can use this
814
898
  * api to control the concurrency of that `Micro` when it is run.
@@ -879,8 +963,9 @@ const unsafeMakeOptions = <R, A, E>(
879
963
  if (microDepthState.depth === 1) {
880
964
  microDepthState.maxDepthBeforeYield = envGet(env, currentMaxDepthBeforeYield)
881
965
  }
882
- if (microDepthState.depth >= microDepthState.maxDepthBeforeYield) {
883
- yieldAdd(() => execute(env, onExit))
966
+ const scheduler = env.refs[currentScheduler.key] as MicroScheduler
967
+ if (microDepthState.depth >= microDepthState.maxDepthBeforeYield || scheduler.shouldYield(env)) {
968
+ scheduler.scheduleTask(() => execute(env, onExit), 0)
884
969
  } else {
885
970
  try {
886
971
  run(env, onExit)
@@ -1200,34 +1285,21 @@ export const tryPromise = <A, E>(options: {
1200
1285
  }
1201
1286
  })
1202
1287
 
1203
- const yieldState: {
1204
- tasks: Array<() => void>
1205
- working: boolean
1206
- } = globalValue("effect/Micro/yieldState", () => ({
1207
- tasks: [],
1208
- working: false
1209
- }))
1210
-
1211
- const yieldRunTasks = () => {
1212
- const tasks = yieldState.tasks
1213
- yieldState.tasks = []
1214
- for (let i = 0, len = tasks.length; i < len; i++) {
1215
- tasks[i]()
1216
- }
1217
- }
1218
-
1219
- const setImmediate = "setImmediate" in globalThis ? globalThis.setImmediate : (f: () => void) => setTimeout(f, 0)
1220
-
1221
- const yieldAdd = (task: () => void) => {
1222
- yieldState.tasks.push(task)
1223
- if (!yieldState.working) {
1224
- yieldState.working = true
1225
- setImmediate(() => {
1226
- yieldState.working = false
1227
- yieldRunTasks()
1228
- })
1229
- }
1230
- }
1288
+ /**
1289
+ * Pause the execution of the current `Micro` effect, and resume it on the next
1290
+ * iteration of the event loop.
1291
+ *
1292
+ * You can specify a priority for the task, which will determine when it is
1293
+ * executed relative to other tasks.
1294
+ *
1295
+ * @since 3.4.0
1296
+ * @experimental
1297
+ * @category constructors
1298
+ */
1299
+ export const yieldWithPriority = (priority: number): Micro<void> =>
1300
+ make(function(env, onExit) {
1301
+ envGet(env, currentScheduler).scheduleTask(() => onExit(exitVoid), priority)
1302
+ })
1231
1303
 
1232
1304
  /**
1233
1305
  * Pause the execution of the current `Micro` effect, and resume it on the next
@@ -1237,9 +1309,7 @@ const yieldAdd = (task: () => void) => {
1237
1309
  * @experimental
1238
1310
  * @category constructors
1239
1311
  */
1240
- export const yieldNow: Micro<void> = make(function(_env, onExit) {
1241
- yieldAdd(() => onExit(exitVoid))
1242
- })
1312
+ export const yieldNow: Micro<void> = yieldWithPriority(0)
1243
1313
 
1244
1314
  /**
1245
1315
  * Flush any yielded effects that are waiting to be executed.
@@ -1248,10 +1318,9 @@ export const yieldNow: Micro<void> = make(function(_env, onExit) {
1248
1318
  * @experimental
1249
1319
  * @category constructors
1250
1320
  */
1251
- export const yieldFlush: Micro<void> = sync(function() {
1252
- while (yieldState.tasks.length > 0) {
1253
- yieldRunTasks()
1254
- }
1321
+ export const yieldFlush: Micro<void> = make(function(env, onExit) {
1322
+ envGet(env, currentScheduler).flush()
1323
+ onExit(exitVoid)
1255
1324
  })
1256
1325
 
1257
1326
  /**
@@ -3687,11 +3756,11 @@ export const fork = <A, E, R>(self: Micro<A, E, R>): Micro<Handle<A, E>, never,
3687
3756
  map[currentAbortSignal.key] = handle._controller.signal
3688
3757
  return map
3689
3758
  })
3690
- yieldAdd(() => {
3759
+ envGet(env, currentScheduler).scheduleTask(() => {
3691
3760
  self[runSymbol](nextEnv, (exit) => {
3692
3761
  handle.emit(exit)
3693
3762
  })
3694
- })
3763
+ }, 0)
3695
3764
  onExit(Either.right(handle))
3696
3765
  })
3697
3766
 
@@ -3714,11 +3783,11 @@ export const forkDaemon = <A, E, R>(self: Micro<A, E, R>): Micro<Handle<A, E>, n
3714
3783
  map[currentAbortSignal.key] = controller.signal
3715
3784
  return map
3716
3785
  })
3717
- yieldAdd(() => {
3786
+ envGet(env, currentScheduler).scheduleTask(() => {
3718
3787
  self[runSymbol](nextEnv, (exit) => {
3719
3788
  handle.emit(exit)
3720
3789
  })
3721
- })
3790
+ }, 0)
3722
3791
  onExit(Either.right(handle))
3723
3792
  })
3724
3793
 
@@ -3790,12 +3859,14 @@ export const runFork = <A, E>(
3790
3859
  effect: Micro<A, E>,
3791
3860
  options?: {
3792
3861
  readonly signal?: AbortSignal | undefined
3862
+ readonly scheduler?: MicroScheduler | undefined
3793
3863
  } | undefined
3794
3864
  ): Handle<A, E> => {
3795
3865
  const controller = new AbortController()
3796
3866
  const refs = Object.create(null)
3797
3867
  refs[currentAbortController.key] = controller
3798
3868
  refs[currentAbortSignal.key] = controller.signal
3869
+ refs[currentScheduler.key] = options?.scheduler ?? new MicroSchedulerDefault()
3799
3870
  const env = envMake(refs)
3800
3871
  const handle = new HandleImpl<A, E>(controller.signal, controller)
3801
3872
  effect[runSymbol](envSet(env, currentAbortSignal, handle._controller.signal), (exit) => {
@@ -3826,6 +3897,7 @@ export const runPromiseExit = <A, E>(
3826
3897
  effect: Micro<A, E>,
3827
3898
  options?: {
3828
3899
  readonly signal?: AbortSignal | undefined
3900
+ readonly scheduler?: MicroScheduler | undefined
3829
3901
  } | undefined
3830
3902
  ): Promise<MicroExit<A, E>> =>
3831
3903
  new Promise((resolve, _reject) => {
@@ -3845,6 +3917,7 @@ export const runPromise = <A, E>(
3845
3917
  effect: Micro<A, E>,
3846
3918
  options?: {
3847
3919
  readonly signal?: AbortSignal | undefined
3920
+ readonly scheduler?: MicroScheduler | undefined
3848
3921
  } | undefined
3849
3922
  ): Promise<A> =>
3850
3923
  runPromiseExit(effect, options).then((exit) => {
@@ -3865,10 +3938,9 @@ export const runPromise = <A, E>(
3865
3938
  * @category execution
3866
3939
  */
3867
3940
  export const runSyncExit = <A, E>(effect: Micro<A, E>): MicroExit<A, E> => {
3868
- const handle = runFork(effect)
3869
- while (yieldState.tasks.length > 0) {
3870
- yieldRunTasks()
3871
- }
3941
+ const scheduler = new MicroSchedulerDefault()
3942
+ const handle = runFork(effect, { scheduler })
3943
+ scheduler.flush()
3872
3944
  const exit = handle.unsafePoll()
3873
3945
  if (exit === null) {
3874
3946
  return exitDie(handle)
package/src/Option.ts CHANGED
@@ -1196,7 +1196,7 @@ export const exists: {
1196
1196
  // -------------------------------------------------------------------------------------
1197
1197
 
1198
1198
  /**
1199
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
1199
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
1200
1200
  *
1201
1201
  * Here's how the do simulation works:
1202
1202
  *
@@ -1244,7 +1244,7 @@ const let_: {
1244
1244
 
1245
1245
  export {
1246
1246
  /**
1247
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
1247
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
1248
1248
  *
1249
1249
  * Here's how the do simulation works:
1250
1250
  *
@@ -1277,7 +1277,7 @@ export {
1277
1277
  }
1278
1278
 
1279
1279
  /**
1280
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
1280
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
1281
1281
  *
1282
1282
  * Here's how the do simulation works:
1283
1283
  *
@@ -1319,7 +1319,7 @@ export const bind: {
1319
1319
  } = doNotation.bind<OptionTypeLambda>(map, flatMap)
1320
1320
 
1321
1321
  /**
1322
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
1322
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
1323
1323
  *
1324
1324
  * Here's how the do simulation works:
1325
1325
  *
package/src/Predicate.ts CHANGED
@@ -29,6 +29,45 @@ export interface Refinement<in A, out B extends A> {
29
29
  (a: A): a is B
30
30
  }
31
31
 
32
+ /**
33
+ * @since 3.6.0
34
+ * @category type-level
35
+ */
36
+ export declare namespace Predicate {
37
+ /**
38
+ * @since 3.6.0
39
+ * @category type-level
40
+ */
41
+ export type In<T extends Any> = [T] extends [Predicate<infer _A>] ? _A : never
42
+ /**
43
+ * @since 3.6.0
44
+ * @category type-level
45
+ */
46
+ export type Any = Predicate<any>
47
+ }
48
+
49
+ /**
50
+ * @since 3.6.0
51
+ * @category type-level
52
+ */
53
+ export declare namespace Refinement {
54
+ /**
55
+ * @since 3.6.0
56
+ * @category type-level
57
+ */
58
+ export type In<T extends Any> = [T] extends [Refinement<infer _A, infer _>] ? _A : never
59
+ /**
60
+ * @since 3.6.0
61
+ * @category type-level
62
+ */
63
+ export type Out<T extends Any> = [T] extends [Refinement<infer _, infer _B>] ? _B : never
64
+ /**
65
+ * @since 3.6.0
66
+ * @category type-level
67
+ */
68
+ export type Any = Refinement<any, any>
69
+ }
70
+
32
71
  /**
33
72
  * Given a `Predicate<A>` returns a `Predicate<B>`
34
73
  *
@@ -686,23 +725,44 @@ export const productMany = <A>(
686
725
  * Similar to `Promise.all` but operates on `Predicate`s.
687
726
  *
688
727
  * ```
728
+ * [Refinement<A, B>, Refinement<C, D>, ...] -> Refinement<[A, C, ...], [B, D, ...]>
689
729
  * [Predicate<A>, Predicate<B>, ...] -> Predicate<[A, B, ...]>
730
+ * [Refinement<A, B>, Predicate<C>, ...] -> Refinement<[A, C, ...], [B, C, ...]>
690
731
  * ```
691
732
  *
692
733
  * @since 2.0.0
693
734
  */
694
- export const tuple = <T extends ReadonlyArray<Predicate<any>>>(
695
- ...elements: T
696
- ): Predicate<Readonly<{ [I in keyof T]: [T[I]] extends [Predicate<infer A>] ? A : never }>> => all(elements) as any
735
+ export const tuple: {
736
+ <T extends ReadonlyArray<Predicate.Any>>(
737
+ ...elements: T
738
+ ): [Extract<T[number], Refinement.Any>] extends [never] ? Predicate<{ readonly [I in keyof T]: Predicate.In<T[I]> }>
739
+ : Refinement<
740
+ { readonly [I in keyof T]: T[I] extends Refinement.Any ? Refinement.In<T[I]> : Predicate.In<T[I]> },
741
+ { readonly [I in keyof T]: T[I] extends Refinement.Any ? Refinement.Out<T[I]> : Predicate.In<T[I]> }
742
+ >
743
+ } = (...elements: ReadonlyArray<Predicate.Any>) => all(elements) as any
697
744
 
698
745
  /**
746
+ * ```
747
+ * { ab: Refinement<A, B>; cd: Refinement<C, D>, ... } -> Refinement<{ ab: A; cd: C; ... }, { ab: B; cd: D; ... }>
748
+ * { a: Predicate<A, B>; b: Predicate<B>, ... } -> Predicate<{ a: A; b: B; ... }>
749
+ * { ab: Refinement<A, B>; c: Predicate<C>, ... } -> Refinement<{ ab: A; c: C; ... }, { ab: B; c: С; ... }>
750
+ * ```
751
+ *
699
752
  * @since 2.0.0
700
753
  */
701
- export const struct = <R extends Record<string, Predicate<any>>>(
702
- fields: R
703
- ): Predicate<{ readonly [K in keyof R]: [R[K]] extends [Predicate<infer A>] ? A : never }> => {
754
+ export const struct: {
755
+ <R extends Record<string, Predicate.Any>>(
756
+ fields: R
757
+ ): [Extract<R[keyof R], Refinement.Any>] extends [never] ?
758
+ Predicate<{ readonly [K in keyof R]: Predicate.In<R[K]> }> :
759
+ Refinement<
760
+ { readonly [K in keyof R]: R[K] extends Refinement.Any ? Refinement.In<R[K]> : Predicate.In<R[K]> },
761
+ { readonly [K in keyof R]: R[K] extends Refinement.Any ? Refinement.Out<R[K]> : Predicate.In<R[K]> }
762
+ >
763
+ } = (<R extends Record<string, Predicate.Any>>(fields: R) => {
704
764
  const keys = Object.keys(fields)
705
- return (a) => {
765
+ return (a: Record<string, unknown>) => {
706
766
  for (const key of keys) {
707
767
  if (!fields[key](a[key])) {
708
768
  return false
@@ -710,7 +770,7 @@ export const struct = <R extends Record<string, Predicate<any>>>(
710
770
  }
711
771
  return true
712
772
  }
713
- }
773
+ }) as any
714
774
 
715
775
  /**
716
776
  * Negates the result of a given predicate.
package/src/Random.ts CHANGED
@@ -1,11 +1,14 @@
1
1
  /**
2
2
  * @since 2.0.0
3
3
  */
4
+ import type * as Array from "./Array.js"
5
+ import type * as Cause from "./Cause.js"
4
6
  import type * as Chunk from "./Chunk.js"
5
7
  import type * as Context from "./Context.js"
6
8
  import type * as Effect from "./Effect.js"
7
9
  import * as defaultServices from "./internal/defaultServices.js"
8
10
  import * as internal from "./internal/random.js"
11
+ import type * as NonEmptyIterable from "./NonEmptyIterable.js"
9
12
 
10
13
  /**
11
14
  * @since 2.0.0
@@ -103,6 +106,27 @@ export const nextIntBetween: (min: number, max: number) => Effect.Effect<number>
103
106
  */
104
107
  export const shuffle: <A>(elements: Iterable<A>) => Effect.Effect<Chunk.Chunk<A>> = defaultServices.shuffle
105
108
 
109
+ /**
110
+ * Get a random element from an iterable.
111
+ *
112
+ * @example
113
+ * import { Effect, Random } from "effect"
114
+ *
115
+ * Effect.gen(function* () {
116
+ * const randomItem = yield* Random.choice([1, 2, 3])
117
+ * console.log(randomItem)
118
+ * })
119
+ *
120
+ * @since 3.6.0
121
+ * @category constructors
122
+ */
123
+ export const choice: <Self extends Iterable<unknown>>(
124
+ elements: Self
125
+ ) => Self extends NonEmptyIterable.NonEmptyIterable<infer A> ? Effect.Effect<A>
126
+ : Self extends Array.NonEmptyReadonlyArray<infer A> ? Effect.Effect<A>
127
+ : Self extends Iterable<infer A> ? Effect.Effect<A, Cause.NoSuchElementException>
128
+ : never = defaultServices.choice
129
+
106
130
  /**
107
131
  * Retreives the `Random` service from the context and uses it to run the
108
132
  * specified workflow.