Created
October 26, 2022 14:28
-
-
Save 7h3kk1d/eeeb1f2e6ee768971c47e2d63f1c688c to your computer and use it in GitHub Desktop.
Transactional Example
This file contains 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
public final class Transactional<M extends MonadRec<?, M>, Cancel, Context, A> implements MonadT<M, A, Transactional<M, Cancel, Context, ?>, Transactional<?, Cancel, Context, ?>> { | |
private final Pure<M> pure; | |
private final ReaderT<Context, M, Either<Cancel, A>> run; | |
public Transactional(Pure<M> pure, ReaderT<Context, M, Either<Cancel, A>> run) { | |
this.pure = pure; | |
this.run = run; | |
} | |
@Override | |
public <B> Transactional<M, Cancel, Context, B> trampolineM(Fn1<? super A, ? extends MonadRec<RecursiveResult<A, B>, Transactional<M, Cancel, Context, ?>>> fn) { | |
return new Transactional<>(pure, eitherT(run) | |
.trampolineM(a -> { | |
Transactional<M, Cancel, Context, RecursiveResult<A, B>> coerce = fn.apply(a) | |
.coerce(); | |
return eitherT(coerce.run); | |
}).runEitherT()); | |
} | |
@Override | |
public <B> Transactional<M, Cancel, Context, B> flatMap(Fn1<? super A, ? extends Monad<B, Transactional<M, Cancel, Context, ?>>> f) { | |
EitherT<ReaderT<Context, M, ?>, Cancel, B> readerTCancelBEitherT = eitherT(run).flatMap(a -> { | |
Transactional<M, Cancel, Context, B> apply = f.apply(a).coerce(); | |
ReaderT<Context, M, Either<Cancel, B>> run1 = apply.run; | |
return eitherT(run1); | |
}); | |
return new Transactional<>(pure, readerTCancelBEitherT.runEitherT()); | |
} | |
@Override | |
public <B> Transactional<M, Cancel, Context, B> pure(B b) { | |
Pure<ReaderT<Context, M, ?>> readerTPure = ReaderT.pureReaderT(pure); | |
ReaderT<Context, M, Either<Cancel, B>> apply = readerTPure.apply(right(b)); | |
return new Transactional<>(pure, apply); | |
} | |
@Override | |
public <B, N extends MonadRec<?, N>> Transactional<N, Cancel, Context, B> lift(MonadRec<B, N> mb) { | |
Lift<ReaderT<Context, ?, ?>> readerTLift = ReaderT.liftReaderT(); | |
return new Transactional<>(mb::pure, readerTLift.<B, N, ReaderT<Context, N, B>>apply(mb) | |
.fmap(Either::right)); | |
} | |
public MonadRec<Either<Cancel, A>, M> run(Context context) { | |
return run.runReaderT(context); | |
} | |
} |
This file contains 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
public class TransactionExample { | |
public static void main(String[] args) { | |
Transactor<IO<?>, Unit, String> transactor = new Transactor<>() { | |
@Override | |
public <A> IO<Either<String, A>> runTransactional(Transactional<IO<?>, String, Unit, A> transactional) { | |
Unit connection = UNIT; | |
return IO.io(() -> System.out.println("Starting Transaction")) | |
.discardL(transactional.run(connection) | |
.<IO<Either<String, A>>>coerce() | |
.flatMap(e -> e.match(s -> IO.io(() -> System.err.printf("Rolling back transaction due to %s%n", s)), | |
__ -> IO.io(() -> System.out.println("Committing Transaction"))) | |
.fmap(constantly(e)))); | |
} | |
}; | |
Transactional<IO<?>, String, Unit, Integer> fetchOddNumber = new Transactional<>(pureIO(), readerT(context -> IO.io(() -> System.out.println("Fetching data")) | |
.fmap(constantly(7)) | |
.fmap(Either::right))); | |
Transactional<IO<?>, String, Unit, Integer> fetchEvenNumber = new Transactional<>(pureIO(), readerT(context -> IO.io(() -> System.out.println("Fetching data")) | |
.fmap(constantly(8)) | |
.fmap(Either::right))); | |
transactor.runTransactional(fetchOddNumber.flatMap(rollBackWhenOdd())) | |
.<IO<Either<String, Unit>>>coerce().unsafePerformIO(); | |
transactor.runTransactional(fetchEvenNumber.flatMap(rollBackWhenOdd())) | |
.<IO<Either<String, Unit>>>coerce().unsafePerformIO(); | |
} | |
private static Fn1<Integer, Monad<Unit, Transactional<IO<?>, String, Unit, ?>>> rollBackWhenOdd() { | |
return integer -> { | |
if (integer % 2 == 0) { | |
return new Transactional<>(pureIO(), readerT(__ -> io(right(UNIT)))); // Commit | |
} | |
return new Transactional<>(pureIO(), readerT(__ -> io(left("Trigger rollback because odd integer")))); // Cancel; | |
}; | |
} | |
} |
This file contains 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
public interface Transactor<M extends MonadRec<?, M>, Context, Cancel> { | |
<A> MonadRec<Either<Cancel, A>, M> runTransactional(Transactional<M, Cancel, Context, A> transactional); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment