import { Driver } from "@effect/core/io/Schedule/Driver" import { DurationInternal } from "@tsplus/stdlib/data/Duration" /** * Returns a driver that can be used to step the schedule, appropriately * handling sleeping. * * @tsplus getter effect/core/io/Schedule driver */ export function driver( self: Schedule ): Effect> { return Ref.make, State]>([Maybe.none, self.initial]).map((ref) => { const last: Effect = ref.get.flatMap(([element, _]) => element.fold(Effect.failSync(new NoSuchElement()), (out) => Effect.succeed(out)) ) const reset: Effect = ref.set([Maybe.none, self.initial]) const state: Effect = ref.get.map((tuple) => tuple[1]) return new Driver(next(self, ref), last, reset, state) }) } function next( self: Schedule, ref: Ref, State]> ) { return (input: In): Effect, Out> => Do(($) => { const state = $(ref.get.map((tuple) => tuple[1])) const now = $(Clock.currentTime) const decision = $(self.step(now, input, state)) return { now, decision } }).flatMap(({ now, decision: [state, out, decision] }) => decision._tag === "Done" ? ref.set([Maybe.some(out), state]) .zipRight(Effect.fail(Maybe.none)) : ref.set([Maybe.some(out), state]) .zipRight( Effect.sleep(new DurationInternal(decision.intervals.start - now)).as(out) ) ) }