Handling Nested Service Access in Effect: Is Yielding Services from Standalone Functions Acceptable?

Hi everyone, I'm new to Effect and I wanted to say thank you for creating this amazing library.
I have a question about how to deal with nested services access.
Let's say I have the following code:

// service-b.ts
class ServiceB extends Effect.Tag("ServiceB")<
  ServiceB,
  { sayHello: () => string, finallyDoIt: () => string}
>() {
  static Live = Layer.succeed(ServiceB, {
    sayHello: () => "hey",
    finallyDoIt: () => "ok"
  });
}

// service-a.ts
const doSomethingElse = () => Effect.gen(function* () {
  const serviceB = yield* ServiceB;

  return serviceB.finallyDoIt();
});

const make = Effect.gen(function* () {
  const serviceB = yield* ServiceB;

  return {
    sayHello: () => {
      return serviceB.sayHello();
    },
    doSomething: () => {
      return doSomethingElse().pipe(Effect.provideService(ServiceB, serviceB));
    },
  };
});

class ServiceA extends Effect.Tag("ServiceA")<
  ServiceA,
  Effect.Effect.Success<typeof make>
>() {
  static Live = Layer.effect(this, make).pipe(Layer.provide(ServiceB.Live));
}


Inside doSomethingElse I yield ServiceB, and to avoid the dependency to bubble up, I provide it as part of the doSomething function body in ServiceA.
Is this an acceptable solution?
I could change doSomethingElse to be a service or move it inside
make
, but the whole point here is for me to understand if it's possible (and if it makes sense) to yield services from a standalone Effect function.

Thanks 🙏
Was this page helpful?