Java Try Monad

Продолжаем эксперименты с java. Когда с версией 1.8 появились элементы функционального программирования я был очень рад. Ибо действительно получилось очень удобно и красиво.
Все очень органично смотрелось в классическом ООП коде. Но на мой взгляд не получило должного развития. Ну или это только для фанатов функционального программирования и Racket :)
Так вот, регулярно, при миграции старого кода встречаются места где какой то код обернут в try/catch и просто возвращает fallback значение в случае исключительной ситуации. Частая ситуация при распознавании дат, чисел и прочих кастомных форматов.
С использованием классических try/catch в современном коде - особенно на stream api, вписывается не очень. А тянуть в зависимости для этого цельный VAVR не всегда позволяют обстоятельства.

В своих проектах я постоянно использую такое расширение.

Монад:

public record Try<T>(T value, Exception error) {

  public static <T> Try<T> of(ThrowingSupplier<T> supplier) {
    try {
      return new Try<>(supplier.get(), null);
    } catch (Exception e) {
      return new Try<>(null, e);
    }
  }

  public T onError(T fallback) {
    return error == null ? value : fallback;
  }
}

и к нему функциональный интерфейс:

@FunctionalInterface
public interface ThrowingSupplier<T> {
  T get() throws Exception;
}

теперь в итоге когда нам надо скажем безопасно распознать Integer/Instant/etc…

Integer value = Try.of(() -> Integer.parseInt(fromSomewhere))
    .onError(0);

очень красиво вписываемся в стандартные java fp extensions.