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

endless.core.interpret.EntityTLiftInstance.scala Maven / Gradle / Ivy

There is a newer version: 0.31.0
Show newest version
package endless.core.interpret

import cats.Monad
import cats.conversions.all.*
import cats.data.NonEmptyChain
import cats.syntax.applicative.*
import cats.syntax.either.*
import cats.syntax.flatMap.*
import cats.syntax.functor.*
import endless.core.entity.Entity

class EntityTLiftInstance[F[_], S, E](implicit fMonad: Monad[F])
    extends Entity[EntityT[F, S, E, *], S, E]
    with Monad[EntityT[F, S, E, *]] {
  implicit lazy val monad: Monad[EntityT[F, S, E, *]] = new Monad[EntityT[F, S, E, *]] {
    def pure[A](x: A): EntityT[F, S, E, A] = EntityT.purr(x)

    def flatMap[A, B](fa: EntityT[F, S, E, A])(f: A => EntityT[F, S, E, B]): EntityT[F, S, E, B] =
      fa.flatMap(f)

    def tailRecM[A, B](a: A)(f: A => EntityT[F, S, E, Either[A, B]]): EntityT[F, S, E, B] =
      new EntityT[F, S, E, B]((folder, events) =>
        fMonad.tailRecM((events, a)) { case (events, a) =>
          f(a).runAcc(folder, events).flatMap {
            case Right((nextEvents, Left(nextA))) =>
              f(nextA).runAcc(folder, nextEvents).map {
                case Right((nextNextEvents, Left(a))) =>
                  (nextNextEvents, a).asLeft // we keep digging
                case Right((nextNextEvents, Right(b))) => (nextNextEvents, b).asRight.asRight
                case Left(invalidFoldReason)           => invalidFoldReason.asLeft.asRight
              }
            case Right((nextEvents, Right(b))) => (nextEvents, b).asRight.asRight.pure[F]
            case Left(invalidFoldReason)       => invalidFoldReason.asLeft.asRight.pure[F]
          }
        }
      )
  }

  override def read: EntityT[F, S, E, Option[S]] = EntityT.reader[F, S, E]
  override def write(event: E, other: E*): EntityT[F, S, E, Unit] =
    EntityT.writer(NonEmptyChain(event, other *))

  def pure[A](x: A): EntityT[F, S, E, A] = monad.pure(x)

  def flatMap[A, B](fa: EntityT[F, S, E, A])(f: A => EntityT[F, S, E, B]): EntityT[F, S, E, B] =
    monad.flatMap(fa)(f)

  def tailRecM[A, B](a: A)(f: A => EntityT[F, S, E, Either[A, B]]): EntityT[F, S, E, B] =
    monad.tailRecM(a)(f)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy