### Question:
ScheduleImpl implements SealedSchedule<F, A, B>, Schedule.Update<F, S, A>, Schedule.Extract<A, S, B> { @SuppressWarnings("unchecked") @Override public <C> Schedule<F, A, Tuple2<B, C>> zip(Schedule<F, A, C> other) { return _zip((ScheduleImpl<F, ?, A, C>) other); } private  ScheduleImpl(Monad<F> monad, Timer<F> timer); abstract Kind<F, S> initial(); @Override Monad<F> monad(); @Override Timer<F> timer(); @Override Schedule<F, A, C> map(Function1<? super B, ? extends C> mapper); @Override Schedule<F, C, B> contramap(Function1<? super C, ? extends A> comap); Schedule<F, A, B> andThen(Schedule<F, A, B> next); @SuppressWarnings("unchecked") Schedule<F, A, Either<B, C>> andThenEither(Schedule<F, A, C> next); @SuppressWarnings("unchecked") @Override Schedule<F, A, Tuple2<B, C>> zip(Schedule<F, A, C> other); @SuppressWarnings("unchecked") @Override Schedule<F, A, C> compose(Schedule<F, B, C> other); @Override Schedule<F, A, Z> foldM(Z zero, Function2<? super Z, ? super B, ? extends Kind<F, Either<Unit, ? extends Z>>> next); @Override Schedule<F, A, B> addDelayM(Function1<B, Kind<F, Duration>> map); @Override Schedule<F, A, B> untilInputM(Function1<A, Kind<F, Boolean>> condition); @Override Schedule<F, A, B> untilOutputM(Function1<B, Kind<F, Boolean>> condition); @Override Schedule<F, A, B> check(Function2<A, B, Kind<F, Boolean>> condition); static ScheduleImpl<F, S, A, B> of(
      Monad<F> monad,
      Timer<F> timer,
      Kind<F, S> initial, 
      Update<F, S, A> update,
      Extract<A, S, B> extract);  }### Answer:
@Test public void retryDelay(@Mock Producer<String> console) { when(console.get()).thenThrow(RuntimeException.class).thenReturn("hola"); IO<String> read = IO.task(console::get); Schedule<IO_, Throwable, Integer> recurs = scheduleOfIO.recurs(2); Schedule<IO_, Throwable, Integer> spaced = scheduleOfIO.spaced(Duration.ofMillis(500)); IO<Tuple2<Duration, String>> retry = monadError.retry(read, recurs.zip(spaced)).fix(toIO()).timed(); Tuple2<Duration, String> result = retry.unsafeRunSync(); assertTrue(result.get1().toMillis() > 500); assertEquals("hola", result.get2()); verify(console, times(2)).get(); }