import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

sealed interface Optional<T> {

    record Empty<T>() implements Optional<T> { }
    record Present<T>(T value) implements Optional<T> {}

    default <R> Optional<R> map(Function<T, R> mapper) {
        return switch (this) {
            case Present<T>(var value) -> new Present<>(mapper.apply(value));
            case Empty<T> _ -> new Empty<>();
        };
    }

    default <R> Optional<R> flatMap(Function<T, Optional<R>> mapper) {
        return switch (this) {
            case Present<T>(var value) -> mapper.apply(value);
            case Empty<T> _ -> new Empty<>();
        };
    }

    default <R> R fold(Supplier<R> onEmpty, Function<T, R> onPresent) {
        return switch (this) {
            case Present<T>(var value) -> onPresent.apply(value);
            case Empty<T> _ -> onEmpty.get();
        };
    }

    default Optional<T> filter(Predicate<T> filter) {
        return switch (this) {
            case Present<T>(var value) when filter.test(value) -> this;
            case Present<T> _ -> new Empty<>();
            case Empty<T> _ -> new Empty<>();
        };
    }
}