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

hael.jjm-core_2.13.0.2.3.source-code.DotKleisli.scala Maven / Gradle / Ivy

The newest version!
package jjm

import cats.~>
import cats.Id
import cats.FlatMap
import cats.implicits._

trait DotKleisli[F[_], A <: Dot] { self =>
  def apply(a: A): F[a.Out]

  // TODO: compose (flat), composeF (nested), composeM (monadic), ...?
  // can these even be implemented? bc of the issue of having a value-level map between Dots

  // TODO sequencing and binding under the dot

  // TODO pair results
  // def product[G[_]]

  def andThenK[G[_]](trans: F ~> G): DotKleisli[G, A] =
    new DotKleisli[G, A] { def apply(a: A): G[a.Out] = trans(self(a)) }

  // TODO this needs a better name
  def andThenDotK[G[_]](dotTrans: DotKleisli[λ[B => F[B] => G[B]], A]): DotKleisli[G, A] =
    new DotKleisli[G, A] { def apply(a: A): G[a.Out] = dotTrans(a)(self(a)) }

  // TODO composeDotK
  
  def dotFlatMap[G[_]](
    f: DotKleisli[λ[B => B => F[G[B]]], A])(
    implicit fm: FlatMap[F]
  ): DotKleisli[λ[B => F[G[B]]], A] =
    new DotKleisli[λ[B => F[G[B]]], A] { def apply(a: A): F[G[a.Out]] = self(a).flatMap(f(a)) }

  def dotFlatTap(
    f: DotKleisli[λ[B => B => F[Unit]], A])(
    implicit fm: FlatMap[F]
  ): DotKleisli[F, A] =
    new DotKleisli[F, A] { def apply(a: A): F[a.Out] = self(a).flatTap(f(a)) }

  def toFunctionK: DotFunctionK[F, A] = new DotFunctionK[F, A] {
    def apply[B](dot: A { type Out = B }) = self(dot)
  }

  def toFunction[B](
    f: DotKleisli[λ[A => F[A] => B], A]
  ): A => B = (a: A) => f(a)(self(a))

  def toFunction[B](
    f: F ~> λ[A => B]
  ): A => B = (a: A) => f(self(a))

  def toDotKleisliGraph(implicit fin: Finite[A]) =
    DotKleisliGraph.fromDotKleisli(this)
}

object DotKleisli {
  val unit = new DotKleisli[Id, DotUnit] {
    override def apply(a: DotUnit) = ()
  }

  def fromFunctionK[F[_], A <: Dot](f: DotFunctionK[F, A]) =
    new DotKleisli[F, A] {
      @inline def apply(a: A): F[a.Out] = _apply[a.Out](a)
      @inline private[this] def _apply[B](req: A { type Out = B }): F[B] = f(req)
    }

  // TODO does this make any sense

  // type Const[C, A] = C

  // def const[F[_], A <: Dot, C](c: F[C]) = new DotKleisli[Lambda[B => F[Const[C, ?]]], A] {
  //   def apply(a: A): Const[C, a.Out] = c
  // }

  // TODO: typeclass instances
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy