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

org.atnos.eff.ChooseInterpretation.scala Maven / Gradle / Ivy

The newest version!
package org.atnos.eff

import Eff._
import cats._
import cats.syntax.all._
import scala.annotation.tailrec

trait ChooseInterpretation {

  def runChoose[R, U, A, F[_]: Alternative](r: Eff[R, A])(implicit m: Member.Aux[Choose, R, U]): Eff[U, F[A]] = {
    def lastRun(l: Last[R]): Last[U] =
      l match {
        case Last(None) => Last[U](None)
        case Last(Some(last)) => Last.eff(runChoose[R, U, Unit, F](last.value).as(()))
      }

    val alternativeF = Alternative[F]

    @tailrec
    def go(stack: List[Eff[R, A]], result: Eff[U, F[A]] = EffMonad[U].pure(alternativeF.empty), resultLast: Option[Last[U]] = None): Eff[U, F[A]] =
      stack match {
        case Nil =>
          resultLast match {
            case Some(last) => result.addLast(last)
            case None => result
          }

        case e :: rest =>
          e match {
            case Pure(a, last) =>
              go(rest, (EffMonad[U].pure(alternativeF.pure(a)), result).mapN(alternativeF.combineK), resultLast.map(_ <* lastRun(last)))

            case Impure(NoEffect(a), c, last) =>
              runChoose(c(a).addLast(last))

            case Impure(u: Union[?, ?], c, last) =>
              m.project(u) match {
                case Left(u1) =>
                  val r1 = Impure(u1, c.interpret(runChoose[R, U, A, F])(_.interpret(l => runChoose[R, U, Unit, F](l).void))).addLast(lastRun(last))
                  go(rest, (r1, result).mapN(alternativeF.combineK))

                case Right(choose) =>
                  choose match {
                    case ChooseZero() => go(rest, result)
                    case _ =>
                      val continuation = c.asInstanceOf[Continuation[R, Boolean, A]]
                      go(continuation(false) :: continuation(true) :: rest, result)
                  }
              }

            case ap @ ImpureAp(_, _, _) =>
              go(ap.toMonadic :: rest, result)
          }
      }

    go(List(r))
  }

}

object ChooseInterpretation extends ChooseInterpretation




© 2015 - 2024 Weber Informatics LLC | Privacy Policy