Skip to content

Commit

Permalink
Add more utility overloads in Entity
Browse files Browse the repository at this point in the history
Also make the naming follow with the type of state application function
  • Loading branch information
Jonas Chapuis authored and jchapuis committed Nov 8, 2021
1 parent b792e9e commit 6ba5757
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 10 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ inThisBuild(
scalaVersion := "2.13.7",
Global / onChangedBuildSource := ReloadOnSourceChanges,
PB.protocVersion := "3.17.3", // works on Apple Silicon,
versionPolicyIntention := Compatibility.BinaryAndSourceCompatible,
versionPolicyIntention := Compatibility.None,
versionPolicyIgnoredInternalDependencyVersions := Some(
"^\\d+\\.\\d+\\.\\d+\\+\\d+".r
) // Support for versions generated by sbt-dynver
Expand Down
48 changes: 44 additions & 4 deletions core/src/main/scala/endless/core/typeclass/entity/Entity.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,63 @@ trait Entity[F[_], S, E] extends StateReader[F, S] with EventWriter[F, E] with M
* @param ifUnknown
* left value in case of missing entity
*/
def ifKnown[A, Error](fa: S => F[A])(ifUnknown: => Error): F[Error \/ A] =
def ifKnown[A, Error](fa: S => A)(ifUnknown: => Error): F[Error \/ A] =
ifKnownF[A, Error](s => pure(fa(s)))(ifUnknown)

/** Convenience function which applies `fa` on the state if entity exists and wraps this in a
* `Right`, otherwise returns a `Left` with the provided error value.
* @param fa
* function to apply on state
* @param ifUnknown
* left value in case of missing entity
*/
def ifKnownF[A, Error](fa: S => F[A])(ifUnknown: => Error): F[Error \/ A] =
ifKnownFE[A, Error](s => map(fa(s))(_.asRight))(ifUnknown)

/** Convenience function which applies `fa` on the state if entity exists, otherwise returns a
* `Left` with the provided error value.
* @param fa
* function to apply on state
* @param ifUnknown
* left value in case of missing entity
*/
def ifKnownFE[A, Error](fa: S => F[Error \/ A])(ifUnknown: => Error): F[Error \/ A] =
flatMap(read) {
case Some(state) => map(fa(state))(_.asRight)
case Some(state) => fa(state)
case None => pure(ifUnknown.asLeft)
}

/** Convenience function which returns a in a `Right` if entity doesn't yet exist, otherwise calls
* `ifKnown` with the state and wraps this in a `Left`.
* @param fa
* success value when entity doesn't exist yet
* @param ifKnown
* function to compute left value in case of existing entity
*/
def ifUnknown[A, Error](a: => A)(ifKnown: S => Error): F[Error \/ A] =
ifUnknownF[A, Error](pure(a))(ifKnown)

/** Convenience function which invokes `fa` if entity doesn't yet exist and wraps this in a
* `Right`, otherwise calls `ifKnown` with the state and wraps this in a `Left`.
* @param fa
* success value when entity doesn't exist yet
* @param ifKnown
* function to compute left value in case of existing entity
*/
def ifUnknownF[A, Error](fa: => F[A])(ifKnown: S => Error): F[Error \/ A] =
ifUnknownFE[A, Error](map(fa)(_.asRight))(ifKnown)

/** Convenience function which invokes `fa` if entity doesn't yet exist and wraps this in a
* `Right`, otherwise calls `ifKnown` with the state and wraps this in a `Left`.
* @param fa
* success value when entity doesn't exist yet
* @param ifKnown
* function to compute left value in case of existing entity
*/
def ifUnknown[A, Error](fa: => F[A])(ifKnown: S => Error): F[Error \/ A] =
def ifUnknownFE[A, Error](fa: => F[Error \/ A])(ifKnown: S => Error): F[Error \/ A] =
flatMap(read) {
case None =>
map(fa)(_.asRight)
fa
case Some(state) =>
pure(ifKnown(state).asLeft)
}
Expand Down
10 changes: 5 additions & 5 deletions example/src/main/scala/endless/example/logic/BookingEntity.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,21 @@ final case class BookingEntity[F[_]: Monad: Logger](entity: Entity[F, Booking, B
origin: LatLon,
destination: LatLon
): F[BookingAlreadyExists \/ Unit] =
ifUnknown(
ifUnknownF(
Logger[F].info(show"Creating booking with ID $bookingID") >> write(
BookingPlaced(bookingID, origin, destination, passengerCount)
)
)(_ => BookingAlreadyExists(bookingID))

def get: F[BookingUnknown.type \/ Booking] = ifKnown(_.pure)(BookingUnknown)
def get: F[BookingUnknown.type \/ Booking] = ifKnown(identity)(BookingUnknown)

def changeOrigin(newOrigin: LatLon): F[BookingUnknown.type \/ Unit] =
ifKnown(booking =>
ifKnownF(booking =>
if (booking.origin =!= newOrigin) entity.write(OriginChanged(newOrigin)) else ().pure
)(BookingUnknown)

def changeDestination(newDestination: LatLon): F[BookingUnknown.type \/ Unit] =
ifKnown(booking =>
ifKnownF(booking =>
if (booking.destination =!= newDestination) entity.write(DestinationChanged(newDestination))
else ().pure
)(BookingUnknown)
Expand All @@ -52,7 +52,7 @@ final case class BookingEntity[F[_]: Monad: Logger](entity: Entity[F, Booking, B
): F[BookingUnknown.type \/ Unit] = changeOrigin(newOrigin) >> changeDestination(newDestination)

def cancel: F[BookingAlg.BookingUnknown.type \/ Unit] =
ifKnown(booking => if (!booking.cancelled) entity.write(BookingCancelled) else ().pure)(
ifKnownF(booking => if (!booking.cancelled) entity.write(BookingCancelled) else ().pure)(
BookingUnknown
)
}
Expand Down

0 comments on commit 6ba5757

Please sign in to comment.