code: public final IO<A> exceptionally(Function<? super Throwable, ? extends A> recoveryFn) {
          return new IO<A>() {
              @Override
              public A unsafePerformIO() {
                  return Try.trying(IO.this::unsafePerformIO).recover(recoveryFn);
              }
  
              @Override
              public CompletableFuture<A> unsafePerformAsyncIO(Executor executor) {
                  return IO.this.unsafePerformAsyncIO(executor).exceptionally(recoveryFn::apply);
              }
          };
      }
docs: Given a function from any {@link Throwable} to the result type <code>A</code>, if this {@link IO} successfully
  yields a result, return it; otherwise, map the {@link Throwable} to the result type and return that.
  
  @param recoveryFn the recovery function
  @return the guarded {@link IO}