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

cats.data.Nested.scala Maven / Gradle / Ivy

The newest version!
package cats
package data

/** Similar to [[cats.data.Tuple2K]], but for nested composition.
 *
 * For instance, since both `List` and `Option` have a `Functor`, then so does
 * `List[Option[_]]`. This is represented by this data type via the instantiation
 * `Nested[List, Option, *]`.
 *
 * {{{
 * scala> import cats.Functor
 * scala> import cats.data.Nested
 * scala> import cats.implicits._
 * scala> val listOption: List[Option[Int]] = List(Some(1), None)
 * scala> val f: Int => String = i => (i * 2).toString
 * scala> Functor[List].map(listOption)(opt => opt.map(f))
 * res0: List[Option[String]] = List(Some(2), None)
 * scala> val nested: Nested[List, Option, Int] = Nested(listOption)
 * scala> val result: Nested[List, Option, String] = Functor[Nested[List, Option, *]].map(nested)(f)
 * scala> result.value
 * res1: List[Option[String]] = List(Some(2), None)
 * }}}
 */
final case class Nested[F[_], G[_], A](value: F[G[A]]) {

  /**
   * Modify the context `F` using transformation `f`.
   */
  def mapK[H[_]](f: F ~> H): Nested[H, G, A] =
    Nested(f(value))

}

object Nested extends NestedInstances

sealed abstract private[data] class NestedInstances extends NestedInstances0 {
  implicit def catsDataEqForNested[F[_], G[_], A](implicit FGA: Eq[F[G[A]]]): Eq[Nested[F, G, A]] =
    Eq.by[Nested[F, G, A], F[G[A]]](_.value)

  implicit def catsDataNonEmptyTraverseForNested[F[_]: NonEmptyTraverse, G[_]: NonEmptyTraverse]
    : NonEmptyTraverse[Nested[F, G, *]] =
    new NestedNonEmptyTraverse[F, G] {
      val FG: NonEmptyTraverse[λ[α => F[G[α]]]] = NonEmptyTraverse[F].compose[G]
    }

  implicit def catsDataContravariantMonoidalForApplicativeForNested[F[_]: Applicative, G[_]: ContravariantMonoidal]
    : ContravariantMonoidal[Nested[F, G, *]] =
    new NestedContravariantMonoidal[F, G] with NestedContravariant[F, G] {
      val FG: ContravariantMonoidal[λ[α => F[G[α]]]] = Applicative[F].composeContravariantMonoidal[G]
    }

  implicit def catsDataDeferForNested[F[_], G[_]](implicit F: Defer[F]): Defer[Nested[F, G, *]] =
    new Defer[Nested[F, G, *]] {
      def defer[A](fa: => Nested[F, G, A]): Nested[F, G, A] =
        Nested(F.defer(fa.value))
    }

  implicit def catsDataTraverseFilterForNested[F[_], G[_]](implicit F0: Traverse[F],
                                                           G0: TraverseFilter[G]): TraverseFilter[Nested[F, G, *]] =
    new NestedTraverseFilter[F, G] {
      implicit val F: Traverse[F] = F0
      implicit val G: TraverseFilter[G] = G0
    }
}

sealed abstract private[data] class NestedInstances0 extends NestedInstances1 {
  implicit def catsDataTraverseForNested[F[_]: Traverse, G[_]: Traverse]: Traverse[Nested[F, G, *]] =
    new NestedTraverse[F, G] {
      val FG: Traverse[λ[α => F[G[α]]]] = Traverse[F].compose[G]
    }

  implicit def catsDataFunctorFilterForNested[F[_], G[_]](implicit F0: Functor[F],
                                                          G0: FunctorFilter[G]): FunctorFilter[Nested[F, G, *]] =
    new NestedFunctorFilter[F, G] {
      implicit val F: Functor[F] = F0
      implicit val G: FunctorFilter[G] = G0
    }
}

sealed abstract private[data] class NestedInstances1 extends NestedInstances2 {
  implicit def catsDataReducibleForNested[F[_]: Reducible, G[_]: Reducible]: Reducible[Nested[F, G, *]] =
    new NestedReducible[F, G] {
      val FG: Reducible[λ[α => F[G[α]]]] = Reducible[F].compose[G]
    }

  implicit def catsDataFunctorForContravariantForNested[F[_]: Contravariant, G[_]: Contravariant]
    : Functor[Nested[F, G, *]] =
    new NestedFunctor[F, G] {
      val FG: Functor[λ[α => F[G[α]]]] = Contravariant[F].compose[G]
    }
}

sealed abstract private[data] class NestedInstances2 extends NestedInstances3 {
  implicit def catsDataFoldableForNested[F[_]: Foldable, G[_]: Foldable]: Foldable[Nested[F, G, *]] =
    new NestedFoldable[F, G] {
      val FG: Foldable[λ[α => F[G[α]]]] = Foldable[F].compose[G]
    }

  implicit def catsDataContravariantForCovariantNested[F[_]: Contravariant, G[_]: Functor]
    : Contravariant[Nested[F, G, *]] =
    new NestedContravariant[F, G] {
      val FG: Contravariant[λ[α => F[G[α]]]] = Contravariant[F].composeFunctor[G]
    }
}

sealed abstract private[data] class NestedInstances3 extends NestedInstances4 {
  implicit def catsDataAlternativeForNested[F[_]: Alternative, G[_]: Applicative]: Alternative[Nested[F, G, *]] =
    new NestedAlternative[F, G] {
      val FG: Alternative[λ[α => F[G[α]]]] = Alternative[F].compose[G]
    }

  implicit def catsDataContravariantForContravariantNested[F[_]: Functor, G[_]: Contravariant]
    : Contravariant[Nested[F, G, *]] =
    new NestedContravariant[F, G] {
      val FG: Contravariant[λ[α => F[G[α]]]] = Functor[F].composeContravariant[G]
    }
}

sealed abstract private[data] class NestedInstances4 extends NestedInstances5 {
  implicit def catsDataApplicativeErrorForNested[F[_], G[_], E](
    implicit F: ApplicativeError[F, E],
    G0: Applicative[G]
  ): ApplicativeError[Nested[F, G, *], E] =
    new NestedApplicativeError[F, G, E] {
      val G: Applicative[G] = G0

      val AEF: ApplicativeError[F, E] = ApplicativeError[F, E]
    }

}

sealed abstract private[data] class NestedInstances5 extends NestedInstances6 {
  implicit def catsDataCommutativeApplicativeForNestedContravariant[F[_]: CommutativeApplicative, G[_]: CommutativeApplicative]
    : CommutativeApplicative[Nested[F, G, *]] =
    new NestedApplicative[F, G] with CommutativeApplicative[Nested[F, G, *]] {
      val FG: Applicative[λ[α => F[G[α]]]] = Applicative[F].compose[G]
    }

  implicit def catsDataMonoidKForNested[F[_]: MonoidK, G[_]]: MonoidK[Nested[F, G, *]] =
    new NestedMonoidK[F, G] {
      val FG: MonoidK[λ[α => F[G[α]]]] = MonoidK[F].compose[G]
    }
}

sealed abstract private[data] class NestedInstances6 extends NestedInstances7 {
  implicit def catsDataCommutativeApplyForNestedContravariant[F[_]: CommutativeApply, G[_]: CommutativeApply]
    : CommutativeApply[Nested[F, G, *]] =
    new NestedApply[F, G] with CommutativeApply[Nested[F, G, *]] {
      val FG: Apply[λ[α => F[G[α]]]] = Apply[F].compose[G]
    }

  implicit def catsDataSemigroupKForNested[F[_]: SemigroupK, G[_]]: SemigroupK[Nested[F, G, *]] =
    new NestedSemigroupK[F, G] {
      val FG: SemigroupK[λ[α => F[G[α]]]] = SemigroupK[F].compose[G]
    }
}

sealed abstract private[data] class NestedInstances7 extends NestedInstances8 {
  implicit def catsDataApplicativeForNested[F[_]: Applicative, G[_]: Applicative]: Applicative[Nested[F, G, *]] =
    new NestedApplicative[F, G] {
      val FG: Applicative[λ[α => F[G[α]]]] = Applicative[F].compose[G]
    }
}

sealed abstract private[data] class NestedInstances8 extends NestedInstances9 {
  implicit def catsDataApplyForNested[F[_]: Apply, G[_]: Apply]: Apply[Nested[F, G, *]] =
    new NestedApply[F, G] {
      val FG: Apply[λ[α => F[G[α]]]] = Apply[F].compose[G]
    }

  implicit def catsDataDistributiveForNested[F[_]: Distributive, G[_]: Distributive]: Distributive[Nested[F, G, *]] =
    new NestedDistributive[F, G] {
      val FG: Distributive[λ[α => F[G[α]]]] = Distributive[F].compose[G]
    }
}

sealed abstract private[data] class NestedInstances9 extends NestedInstances10 {
  implicit def catsDataInvariantSemigroupalApplyForNested[F[_]: InvariantSemigroupal, G[_]: Apply]
    : InvariantSemigroupal[Nested[F, G, *]] =
    new NestedInvariantSemigroupalApply[F, G] {
      val FG: InvariantSemigroupal[λ[α => F[G[α]]]] = InvariantSemigroupal[F].composeApply[G]
    }
}

sealed abstract private[data] class NestedInstances10 extends NestedInstances11 {
  implicit def catsDataFunctorForNested[F[_]: Functor, G[_]: Functor]: Functor[Nested[F, G, *]] =
    new NestedFunctor[F, G] {
      val FG: Functor[λ[α => F[G[α]]]] = Functor[F].compose[G]
    }
}

sealed abstract private[data] class NestedInstances11 extends NestedInstances12 {
  implicit def catsDataInvariantForNested[F[_]: Invariant, G[_]: Invariant]: Invariant[Nested[F, G, *]] =
    new NestedInvariant[F, G] {
      val FG: Invariant[λ[α => F[G[α]]]] = Invariant[F].compose[G]
    }
}

sealed abstract private[data] class NestedInstances12 extends NestedInstances13 {
  implicit def catsDataInvariantForCovariantNested[F[_]: Invariant, G[_]: Functor]: Invariant[Nested[F, G, *]] =
    new NestedInvariant[F, G] {
      val FG: Invariant[λ[α => F[G[α]]]] = Invariant[F].composeFunctor[G]
    }
}

sealed abstract private[data] class NestedInstances13 {
  implicit def catsDataInvariantForNestedContravariant[F[_]: Invariant, G[_]: Contravariant]
    : Invariant[Nested[F, G, *]] =
    new NestedInvariant[F, G] {
      val FG: Invariant[λ[α => F[G[α]]]] = Invariant[F].composeContravariant[G]
    }
}

private[data] trait NestedInvariant[F[_], G[_]] extends Invariant[Nested[F, G, *]] {
  def FG: Invariant[λ[α => F[G[α]]]]

  override def imap[A, B](fga: Nested[F, G, A])(f: A => B)(g: B => A): Nested[F, G, B] =
    Nested(FG.imap(fga.value)(f)(g))
}

private[data] trait NestedFunctor[F[_], G[_]] extends Functor[Nested[F, G, *]] with NestedInvariant[F, G] {
  override def FG: Functor[λ[α => F[G[α]]]]

  override def map[A, B](fga: Nested[F, G, A])(f: A => B): Nested[F, G, B] =
    Nested(FG.map(fga.value)(f))
}

private[data] trait NestedApply[F[_], G[_]] extends Apply[Nested[F, G, *]] with NestedFunctor[F, G] {
  override def FG: Apply[λ[α => F[G[α]]]]

  override def ap[A, B](fgf: Nested[F, G, A => B])(fga: Nested[F, G, A]): Nested[F, G, B] =
    Nested(FG.ap(fgf.value)(fga.value))

  override def product[A, B](fga: Nested[F, G, A], fgb: Nested[F, G, B]): Nested[F, G, (A, B)] =
    Nested(FG.product(fga.value, fgb.value))
}

private[data] trait NestedApplicative[F[_], G[_]] extends Applicative[Nested[F, G, *]] with NestedApply[F, G] {
  def FG: Applicative[λ[α => F[G[α]]]]

  def pure[A](x: A): Nested[F, G, A] = Nested(FG.pure(x))
}

abstract private[data] class NestedApplicativeError[F[_], G[_], E]
    extends ApplicativeError[Nested[F, G, *], E]
    with NestedApplicative[F, G] {
  def G: Applicative[G]
  def AEF: ApplicativeError[F, E]

  def FG: Applicative[λ[α => F[G[α]]]] = AEF.compose[G](G)

  def raiseError[A](e: E): Nested[F, G, A] = Nested(AEF.map(AEF.raiseError[A](e))(G.pure))

  def handleErrorWith[A](fa: Nested[F, G, A])(f: E => Nested[F, G, A]): Nested[F, G, A] =
    Nested(AEF.handleErrorWith(fa.value)(e => f(e).value))

}

private[data] trait NestedSemigroupK[F[_], G[_]] extends SemigroupK[Nested[F, G, *]] {
  def FG: SemigroupK[λ[α => F[G[α]]]]

  def combineK[A](x: Nested[F, G, A], y: Nested[F, G, A]): Nested[F, G, A] = Nested(FG.combineK(x.value, y.value))
}

private[data] trait NestedMonoidK[F[_], G[_]] extends MonoidK[Nested[F, G, *]] with NestedSemigroupK[F, G] {
  def FG: MonoidK[λ[α => F[G[α]]]]

  def empty[A]: Nested[F, G, A] = Nested(FG.empty[A])
}

private[data] trait NestedAlternative[F[_], G[_]]
    extends Alternative[Nested[F, G, *]]
    with NestedApplicative[F, G]
    with NestedMonoidK[F, G] {
  def FG: Alternative[λ[α => F[G[α]]]]
}

private[data] trait NestedFoldable[F[_], G[_]] extends Foldable[Nested[F, G, *]] {
  def FG: Foldable[λ[α => F[G[α]]]]

  def foldLeft[A, B](fga: Nested[F, G, A], b: B)(f: (B, A) => B): B =
    FG.foldLeft(fga.value, b)(f)

  def foldRight[A, B](fga: Nested[F, G, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
    FG.foldRight(fga.value, lb)(f)
}

private[data] trait NestedTraverse[F[_], G[_]]
    extends Traverse[Nested[F, G, *]]
    with NestedFoldable[F, G]
    with NestedFunctor[F, G] {
  def FG: Traverse[λ[α => F[G[α]]]]

  override def traverse[H[_]: Applicative, A, B](fga: Nested[F, G, A])(f: A => H[B]): H[Nested[F, G, B]] =
    Applicative[H].map(FG.traverse(fga.value)(f))(Nested(_))
}

private[data] trait NestedDistributive[F[_], G[_]] extends Distributive[Nested[F, G, *]] with NestedFunctor[F, G] {
  def FG: Distributive[λ[α => F[G[α]]]]

  def distribute[H[_]: Functor, A, B](ha: H[A])(f: A => Nested[F, G, B]): Nested[F, G, H[B]] =
    Nested(FG.distribute(ha) { a =>
      f(a).value
    })
}

private[data] trait NestedReducible[F[_], G[_]] extends Reducible[Nested[F, G, *]] with NestedFoldable[F, G] {
  def FG: Reducible[λ[α => F[G[α]]]]

  def reduceLeftTo[A, B](fga: Nested[F, G, A])(f: A => B)(g: (B, A) => B): B =
    FG.reduceLeftTo(fga.value)(f)(g)

  def reduceRightTo[A, B](fga: Nested[F, G, A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] =
    FG.reduceRightTo(fga.value)(f)(g)
}

private[data] trait NestedNonEmptyTraverse[F[_], G[_]]
    extends NonEmptyTraverse[Nested[F, G, *]]
    with NestedTraverse[F, G]
    with NestedReducible[F, G] {
  def FG: NonEmptyTraverse[λ[α => F[G[α]]]]

  override def nonEmptyTraverse[H[_]: Apply, A, B](fga: Nested[F, G, A])(f: A => H[B]): H[Nested[F, G, B]] =
    Apply[H].map(FG.nonEmptyTraverse(fga.value)(f))(Nested(_))
}

private[data] trait NestedContravariant[F[_], G[_]] extends Contravariant[Nested[F, G, *]] {
  def FG: Contravariant[λ[α => F[G[α]]]]

  override def contramap[A, B](fga: Nested[F, G, A])(f: B => A): Nested[F, G, B] =
    Nested(FG.contramap(fga.value)(f))
}

private[data] trait NestedContravariantMonoidal[F[_], G[_]] extends ContravariantMonoidal[Nested[F, G, *]] {
  def FG: ContravariantMonoidal[λ[α => F[G[α]]]]

  def unit: Nested[F, G, Unit] = Nested(FG.unit)

  def contramap[A, B](fa: Nested[F, G, A])(f: B => A): Nested[F, G, B] =
    Nested(FG.contramap(fa.value)(f))

  def product[A, B](fa: Nested[F, G, A], fb: Nested[F, G, B]): Nested[F, G, (A, B)] =
    Nested(FG.product(fa.value, fb.value))
}

private[data] trait NestedInvariantSemigroupalApply[F[_], G[_]] extends InvariantSemigroupal[Nested[F, G, *]] {
  def FG: InvariantSemigroupal[λ[α => F[G[α]]]]

  def imap[A, B](fa: Nested[F, G, A])(f: A => B)(g: B => A): Nested[F, G, B] =
    Nested(FG.imap(fa.value)(f)(g))

  def product[A, B](fa: Nested[F, G, A], fb: Nested[F, G, B]): Nested[F, G, (A, B)] =
    Nested(FG.product(fa.value, fb.value))
}

abstract private[data] class NestedFunctorFilter[F[_], G[_]] extends FunctorFilter[Nested[F, G, *]] {
  implicit val F: Functor[F]

  implicit val G: FunctorFilter[G]

  def functor: Functor[Nested[F, G, *]] = Nested.catsDataFunctorForNested(F, G.functor)

  def mapFilter[A, B](fa: Nested[F, G, A])(f: (A) => Option[B]): Nested[F, G, B] =
    Nested[F, G, B](F.map(fa.value)(G.mapFilter(_)(f)))

  override def collect[A, B](fa: Nested[F, G, A])(f: PartialFunction[A, B]): Nested[F, G, B] =
    Nested[F, G, B](F.map(fa.value)(G.collect(_)(f)))

  override def flattenOption[A](fa: Nested[F, G, Option[A]]): Nested[F, G, A] =
    Nested[F, G, A](F.map(fa.value)(G.flattenOption))

  override def filter[A](fa: Nested[F, G, A])(f: (A) => Boolean): Nested[F, G, A] =
    Nested[F, G, A](F.map(fa.value)(G.filter(_)(f)))

  override def filterNot[A](fa: Nested[F, G, A])(f: A => Boolean): Nested[F, G, A] =
    Nested[F, G, A](F.map(fa.value)(G.filterNot(_)(f)))

}

abstract private[data] class NestedTraverseFilter[F[_], G[_]]
    extends NestedFunctorFilter[F, G]
    with TraverseFilter[Nested[F, G, *]] {
  implicit val F: Traverse[F]

  implicit val G: TraverseFilter[G]

  def traverse: Traverse[Nested[F, G, *]] = Nested.catsDataTraverseForNested(F, G.traverse)

  override def filterA[H[_], A](
    fa: Nested[F, G, A]
  )(f: A => H[Boolean])(implicit H: Applicative[H]): H[Nested[F, G, A]] =
    H.map(F.traverse(fa.value)(G.filterA[H, A](_)(f)))(Nested[F, G, A])

  def traverseFilter[H[_], A, B](
    fga: Nested[F, G, A]
  )(f: A => H[Option[B]])(implicit H: Applicative[H]): H[Nested[F, G, B]] =
    H.map(F.traverse[H, G[A], G[B]](fga.value)(ga => G.traverseFilter(ga)(f)))(Nested[F, G, B])
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy