Created
October 8, 2025 12:08
-
-
Save Garciat/0db4b5abd9981c132e8ef650ffa707bb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| interface Refinement<T> { | |
| boolean isValid(T value); | |
| static <T, R1 extends Refinement<T>, R2 extends Refinement<T>> And<T, R1, R2> and(R1 r1, R2 r2) { | |
| return new And<>(r1, r2); | |
| } | |
| record And<T, R1 extends Refinement<T>, R2 extends Refinement<T>>(R1 r1, R2 r2) | |
| implements Refinement<T> { | |
| @Override | |
| public boolean isValid(T value) { | |
| return r1.isValid(value) && r2.isValid(value); | |
| } | |
| } | |
| } | |
| interface PositiveI extends Refinement<Integer> { | |
| PositiveI IT = new PositiveI() {}; | |
| @Override | |
| default boolean isValid(Integer value) { | |
| return value > 0; | |
| } | |
| static PositiveI positiveI() { | |
| return IT; | |
| } | |
| } | |
| interface EvenI extends Refinement<Integer> { | |
| EvenI IT = new EvenI() {}; | |
| @Override | |
| default boolean isValid(Integer value) { | |
| return value % 2 == 0; | |
| } | |
| static EvenI evenI() { | |
| return IT; | |
| } | |
| } | |
| interface NonEmpty<C extends Collection<?>> extends Refinement<C> { | |
| @Override | |
| boolean isValid(C value); | |
| static <C extends Collection<?>> NonEmpty<C> nonEmpty() { | |
| return value -> !value.isEmpty(); | |
| } | |
| } | |
| sealed interface TyEq<A, B> { | |
| B cast(A a); | |
| static <T> TyEq<T, T> refl() { | |
| return new Refl<>(); | |
| } | |
| record Refl<T>() implements TyEq<T, T> { | |
| @Override | |
| public T cast(T t) { | |
| return t; | |
| } | |
| } | |
| } | |
| final class Refined<T, R extends Refinement<T>> { | |
| private final T value; | |
| private final R refinement; | |
| private Refined(T value, R refinement) { | |
| this.value = value; | |
| this.refinement = refinement; | |
| } | |
| public <A extends Refinement<T>, B extends Refinement<T>> Refined<T, A> fst( | |
| TyEq<R, Refinement.And<T, A, B>> ty) { | |
| return new Refined<>(value, ty.cast(refinement).r1()); | |
| } | |
| public <A extends Refinement<T>, B extends Refinement<T>> Refined<T, B> snd( | |
| TyEq<R, Refinement.And<T, A, B>> ty) { | |
| return new Refined<>(value, ty.cast(refinement).r2()); | |
| } | |
| public static <T, R extends Refinement<T>> Optional<Refined<T, R>> of(T value, R refinement) { | |
| return refinement.isValid(value) | |
| ? Optional.of(new Refined<>(value, refinement)) | |
| : Optional.empty(); | |
| } | |
| public T value() { | |
| return value; | |
| } | |
| } | |
| class Example { | |
| void f() { | |
| Refined<Integer, Refinement.And<Integer, PositiveI, EvenI>> refined = | |
| Refined.of(2, Refinement.and(PositiveI.IT, EvenI.IT)).orElseThrow(); | |
| wantPositive(refined.fst(TyEq.refl())); | |
| wantEven(refined.snd(TyEq.refl())); | |
| Refined<ImmutableList<Integer>, NonEmpty<ImmutableList<Integer>>> immutableListNonEmptyRefined = | |
| Refined.of(ImmutableList.of(1, 2, 3), NonEmpty.nonEmpty()).orElseThrow(); | |
| } | |
| void wantPositive(Refined<Integer, PositiveI> r) { | |
| System.out.println(r.value()); | |
| } | |
| void wantEven(Refined<Integer, EvenI> r) { | |
| System.out.println(r.value()); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment