import java.util.function.Function;

sealed interface Either<L, R> {
    record Left<L, R>(L left) implements Either<L, R> { }
    record Right<L, R>(R right) implements Either<L, R> {}

    default <T> Either<L, T> map(Function<R, T> mapper) {
        return switch (this) {
            case Left<L, R>(var left) -> new Left<>(left);
            case Right<L, R>(var right) -> new Right<>(mapper.apply(right));
        };
    }

    default <T> Either<T, R> mapError(Function<L, T> mapper) {
        return switch (this) {
            case Left<L, R>(var left) -> new Left<>(mapper.apply(left));
            case Right<L, R>(var right) -> new Right<>(right);
        };
    }

    default <T> Either<L, T> flatMap(Function<R, Either<L, T>> mapper) {
        return switch (this) {
            case Left<L, R>(var left) -> new Left<>(left);
            case Right<L, R>(var right) -> mapper.apply(right);
        };
    }

    default <T> T fold(Function<L, T> leftMapper, Function<R, T> rightMapper) {
        return switch (this) {
            case Left<L, R>(var left) -> leftMapper.apply(left);
            case Right<L, R>(var right) -> rightMapper.apply(right);
        };
    }
}
