diff --git a/.changeset/rare-spiders-occur.md b/.changeset/rare-spiders-occur.md new file mode 100644 index 0000000000..649fa82e89 --- /dev/null +++ b/.changeset/rare-spiders-occur.md @@ -0,0 +1,5 @@ +--- +"effect": minor +--- + +Support `this` argument for `{STM, Either, Option}.gen` diff --git a/packages/effect/src/Either.ts b/packages/effect/src/Either.ts index 4f1566d658..21470727ee 100644 --- a/packages/effect/src/Either.ts +++ b/packages/effect/src/Either.ts @@ -700,7 +700,10 @@ const adapter = Gen.adapter() * @category generators * @since 2.0.0 */ -export const gen: Gen.Gen> = (f) => { +export const gen: Gen.Gen> = (...args) => { + const f = (args.length === 1) + ? args[0] + : args[1].bind(args[0]) const iterator = f(adapter) let state: IteratorYieldResult | IteratorReturnResult = iterator.next() if (state.done) { diff --git a/packages/effect/src/Option.ts b/packages/effect/src/Option.ts index 0824d2c01c..6f9f16e6db 100644 --- a/packages/effect/src/Option.ts +++ b/packages/effect/src/Option.ts @@ -1345,7 +1345,13 @@ const adapter = Gen.adapter() * @category generators * @since 2.0.0 */ -export const gen: Gen.Gen> = (f) => { +export const gen: Gen.Gen> = (...args) => { + let f: any + if (args.length === 1) { + f = args[0] + } else { + f = args[1].bind(args[0]) + } const iterator = f(adapter) let state: IteratorYieldResult | IteratorReturnResult = iterator.next() if (state.done) { diff --git a/packages/effect/src/STM.ts b/packages/effect/src/STM.ts index e084d960c1..e961f9a7f2 100644 --- a/packages/effect/src/STM.ts +++ b/packages/effect/src/STM.ts @@ -1065,8 +1065,13 @@ export interface Adapter { * @since 2.0.0 * @category constructors */ -export const gen: >, AEff>( - f: (resume: Adapter) => Generator +export const gen: >, AEff>( + ...args: + | [ + self: Self, + body: (this: Self, resume: Adapter) => Generator + ] + | [body: (resume: Adapter) => Generator] ) => STM< AEff, [Eff] extends [never] ? never : [Eff] extends [YieldWrap>] ? E : never, diff --git a/packages/effect/src/Utils.ts b/packages/effect/src/Utils.ts index 3c83b02f90..618d0a6d7d 100644 --- a/packages/effect/src/Utils.ts +++ b/packages/effect/src/Utils.ts @@ -172,17 +172,20 @@ export interface Variance { readonly _E: Types.Covariant } -/** - * @category models - * @since 2.0.0 - */ /** * @category models * @since 2.0.0 */ export interface Gen { - | YieldWrap>, A>( - body: (resume: Z) => Generator + | YieldWrap>, A>( + ...args: + | [ + self: Self, + body: (this: Self, resume: Z) => Generator + ] + | [ + body: (resume: Z) => Generator + ] ): Kind< F, [K] extends [Variance] ? R diff --git a/packages/effect/src/internal/stm/stm.ts b/packages/effect/src/internal/stm/stm.ts index e7e847b585..c61b946132 100644 --- a/packages/effect/src/internal/stm/stm.ts +++ b/packages/effect/src/internal/stm/stm.ts @@ -618,8 +618,11 @@ export const fromOption = (option: Option.Option): STM.STM +export const gen: typeof STM.gen = (...args) => suspend(() => { + const f = (args.length === 1) + ? args[0] + : args[1].bind(args[0]) const iterator = f(pipe) const state = iterator.next() const run = ( diff --git a/packages/effect/test/Either.test.ts b/packages/effect/test/Either.test.ts index 889775339d..290b041950 100644 --- a/packages/effect/test/Either.test.ts +++ b/packages/effect/test/Either.test.ts @@ -42,12 +42,16 @@ describe("Either", () => { const f = Either.gen(function*($) { yield* $(Either.left("err")) }) + const g = Either.gen({ context: "testContext" as const }, function*($) { + return yield* $(Either.right(this.context)) + }) expect(a).toEqual(Either.right(3)) expect(b).toEqual(Either.right(10)) expect(c).toEqual(Either.right(undefined)) expect(d).toEqual(Either.right(2)) expect(e).toEqual(Either.left("err")) expect(f).toEqual(Either.left("err")) + expect(g).toEqual(Either.right("testContext")) }) it("exports", () => { diff --git a/packages/effect/test/Option.test.ts b/packages/effect/test/Option.test.ts index 67dbe94541..4ecb0088af 100644 --- a/packages/effect/test/Option.test.ts +++ b/packages/effect/test/Option.test.ts @@ -46,12 +46,17 @@ describe("Option", () => { const f = Option.gen(function*($) { yield* $(Option.none()) }) + + const g = Option.gen({ ctx: "testContext" as const }, function*() { + return yield* Option.some(this.ctx) + }) expect(a).toEqual(Option.some(3)) expect(b).toEqual(Option.some(10)) expect(c).toEqual(Option.some(undefined)) expect(d).toEqual(Option.some(2)) expect(e).toEqual(Option.none()) expect(f).toEqual(Option.none()) + expect(g).toEqual(Option.some("testContext")) }) it("toString", () => { diff --git a/packages/effect/test/STM.test.ts b/packages/effect/test/STM.test.ts index 10946e9f4c..0b72e06b09 100644 --- a/packages/effect/test/STM.test.ts +++ b/packages/effect/test/STM.test.ts @@ -957,6 +957,12 @@ describe("STM", () => { assert.strictEqual(result, "test") })) + it.effect("gen with context", () => + STM.gen({ context: "Context" as const }, function*() { + const result = yield* STM.succeed(this.context) + assert.strictEqual(result, "Context") + })) + it.effect("summarized - returns summary and value", () => Effect.gen(function*($) { const transaction = STM.gen(function*($) {