All Downloads are FREE. Search and download functionalities are using the official Maven repository.

endless.core.entity.StateReaderHelpers.scala Maven / Gradle / Ivy

The newest version!
package endless.core.entity

import cats.Monad
import cats.data.EitherT
import cats.syntax.applicative.*
import cats.syntax.either.*
import cats.syntax.flatMap.*
import cats.syntax.functor.*
import endless.\/

/** Set of convenience functions augmenting `StateReader` (that assume a `Monad` instance exists for
  * `F`)
  * @tparam F
  *   context
  * @tparam S
  *   state
  */
trait StateReaderHelpers[F[_], S] extends StateReader[F, S] {
  implicit def monad: Monad[F]

  /** 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 ifKnown[Error, A](fa: S => A)(ifUnknown: => Error): F[Error \/ A] =
    ifKnownF[Error, A](s => fa(s).pure)(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[Error, A](fa: S => F[A])(ifUnknown: => Error): F[Error \/ A] =
    ifKnownFE[Error, A](s => fa(s).map(_.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[Error, A](fa: S => F[Error \/ A])(ifUnknown: => Error): F[Error \/ A] =
    ifKnownElse(fa)(ifUnknown.asLeft[A].pure)

  /** Convenience function which applies `fa` on the state if entity exists and unwraps EitherT
    * value, 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 ifKnownT[Error, A](fa: S => EitherT[F, Error, A])(ifUnknown: => Error): F[Error \/ A] =
    ifKnownFE(s => fa(s).value)(ifUnknown)

  /** Convenience function which applies `fa` on the state if entity exists, otherwise returns a
    * default value
    *
    * @param fa
    *   function to apply on state
    * @param ifUnknownF
    *   value in case of missing entity in `F` context
    */
  def ifKnownElse[A](fa: S => F[A])(ifUnknownF: => F[A]): F[A] =
    read.flatMap {
      case Some(state) => fa(state)
      case None        => ifUnknownF
    }

  /** 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[Error, A](a: => A)(ifKnown: S => Error): F[Error \/ A] =
    ifUnknownF[Error, A](a.pure)(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[Error, A](fa: => F[A])(ifKnown: S => Error): F[Error \/ A] =
    ifUnknownFE[Error, A](fa.map(_.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 ifUnknownFE[Error, A](fa: => F[Error \/ A])(ifKnown: S => Error): F[Error \/ A] =
    ifUnknownElse(fa)(state => ifKnown(state).asLeft[A].pure)

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

  /** Convenience function which returns a value `fa` in `F` context, otherwise calls `ifKnown` with
    * the state
    *
    * @param fa
    *   value in case of missing entity in `F` context
    * @param ifKnown
    *   function to apply on state
    */
  def ifUnknownElse[A](fa: => F[A])(ifKnown: S => F[A]): F[A] =
    read.flatMap {
      case Some(state) => ifKnown(state)
      case None        => fa
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy