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

io.scalaland.chimney.cats.CatsTotalTransformerImplicits.scala Maven / Gradle / Ivy

package io.scalaland.chimney.cats

import _root_.cats.{CoflatMap, Contravariant, Monad}
import _root_.cats.arrow.{ArrowChoice, CommutativeArrow}
import io.scalaland.chimney.Transformer

/** @since 1.0.0 */
trait CatsTotalTransformerImplicits {

  /** @since 1.0.0 */
  implicit final val catsArrowForTransformer: ArrowChoice[Transformer] & CommutativeArrow[Transformer] =
    new ArrowChoice[Transformer] with CommutativeArrow[Transformer] {
      override def lift[A, B](f: A => B): Transformer[A, B] = f(_)

      override def first[A, B, C](fa: Transformer[A, B]): Transformer[(A, C), (B, C)] =
        pair => fa.transform(pair._1) -> pair._2

      override def compose[A, B, C](f: Transformer[B, C], g: Transformer[A, B]): Transformer[A, C] =
        a => f.transform(g.transform(a))

      override def choose[A, B, C, D](
          f: Transformer[A, C]
      )(
          g: Transformer[B, D]
      ): Transformer[Either[A, B], Either[C, D]] = {
        case Left(a)  => Left(f.transform(a))
        case Right(b) => Right(g.transform(b))
      }
    }

  /** @since 1.0.0 */
  implicit final def catsCovariantForTransformer[Source]
      : Monad[Transformer[Source, *]] & CoflatMap[Transformer[Source, *]] =
    new Monad[Transformer[Source, *]] with CoflatMap[Transformer[Source, *]] {
      override def pure[A](x: A): Transformer[Source, A] = _ => x

      override def flatMap[A, B](fa: Transformer[Source, A])(f: A => Transformer[Source, B]): Transformer[Source, B] =
        src => f(fa.transform(src)).transform(src)

      override def tailRecM[A, B](a: A)(
          f: A => Transformer[Source, Either[A, B]]
      ): Transformer[Source, B] =
        src => {
          @scala.annotation.tailrec
          def loop(a1: A): B = f(a1).transform(src) match {
            case Left(a2) => loop(a2)
            case Right(b) => b
          }
          loop(a)
        }

      override def coflatMap[A, B](
          fa: Transformer[Source, A]
      )(
          f: Transformer[Source, A] => B
      ): Transformer[Source, B] = src => f(fa)
    }

  /** @since 1.0.0 */
  implicit final def catsContravariantForTransformer[Target]: Contravariant[Transformer[*, Target]] =
    new Contravariant[Transformer[*, Target]] {
      def contramap[A, B](fa: Transformer[A, Target])(f: B => A): Transformer[B, Target] =
        b => fa.transform(f(b))
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy