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

libretto.scaletto.impl.ScalaFunction.scala Maven / Gradle / Ivy

The newest version!
package libretto.scaletto.impl

import libretto.util.Async

enum ScalaFunction[A, B] {
  case Direct(f: A => B)
  case Blocking(f: A => B)
  case Asynchronous(f: A => Async[B])
  case Step[A, X, B](f: A => (ScalaFunction[X, B], X)) extends ScalaFunction[A, B]

  def adapt[Z, C](pre: Z => A, post: B => C): ScalaFunction[Z, C] =
    this match {
      case Direct(f)       => Direct(pre andThen f andThen post)
      case Blocking(f)     => Blocking(pre andThen f andThen post)
      case Asynchronous(f) => Asynchronous(z => f(pre(z)).map(post))
      case Step(f)         => Step(z => f(pre(z)) match { case (g, x) => (g.adaptPost(post), x) })
    }

  def adaptPost[C](post: B => C): ScalaFunction[A, C] =
    this match {
      case Direct(f)       => Direct(f andThen post)
      case Blocking(f)     => Blocking(f andThen post)
      case Asynchronous(f) => Asynchronous(a => f(a).map(post))
      case Step(f)         => Step(a => f(a) match { case (g, x) => (g.adaptPost(post), x) })
    }

  def adaptWith[Z, P, C](
    pre: Z => (P, A),
    post: (P, B) => C,
  ): ScalaFunction[Z, C] =
    this match {
      case Direct(f)       => Direct      (z => pre(z) match { case (p, a) => post(p, f(a)) })
      case Blocking(f)     => Blocking    (z => pre(z) match { case (p, a) => post(p, f(a)) })
      case Asynchronous(f) => Asynchronous(z => pre(z) match { case (p, a) => f(a).map(post(p, _)) })
      case Step(f)         => Step        (z => pre(z) match { case (p, a) => val (g, x) = f(a); (g.adaptPost(b => post(p, b)), x) })
    }
}

object ScalaFunction {
  def eval[A, B]: ScalaFunction[(ScalaFunction[A, B], A), B] =
    Step(identity[(ScalaFunction[A, B], A)])
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy