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

proptics.Traversal.scala Maven / Gradle / Ivy

package proptics

import scala.Function.const

import cats.data.{Nested, State}
import cats.syntax.apply._
import cats.syntax.bitraverse._
import cats.{Alternative, Applicative, Bitraverse, Monoid, Traverse}

import proptics.Lens_.liftOptic
import proptics.Traversal_.wander
import proptics.data.Disj
import proptics.internal._
import proptics.profunctor.Corepresentable.Aux
import proptics.profunctor.Wander._
import proptics.profunctor.{Star, Traversing, Wander}
import proptics.rank2types.{LensLike, LensLikeWithIndex, Rank2TypeTraversalLike}
import proptics.syntax.star._
import proptics.syntax.traversal._

/** A [[Traversal_]] is an optic that focuses on zero or more values
  *
  * @tparam S
  *   the source of a [[Traversal_]]
  * @tparam T
  *   the modified source of a [[Traversal_]]
  * @tparam A
  *   the foci of a [[Traversal_]]
  * @tparam B
  *   the modified foci of a [[Traversal_]]
  */
abstract class Traversal_[S, T, A, B] extends Traversal1[S, T, A, B] { self =>
  private[proptics] def apply[P[_, _]](pab: P[A, B])(implicit ev: Wander[P]): P[S, T]

  /** modify the foci type of a [[Traversal_]] using a function, resulting in a change of type to the full structure */
  final def over(f: A => B): S => T = self(f)

  /** modify each focus of a [[Traversal_]] using a Functor, resulting in a change of type to the full structure */
  final override def traverse[F[_]: Applicative](s: S)(f: A => F[B]): F[T] = self[Star[F, *, *]](Star(f)).runStar(s)

  /** try to map a function over this [[Traversal_]], failing if the [[Traversal_]] has no focus. */
  final def failover[F[_]](f: A => B)(s: S)(implicit ev0: Wander[Star[(Disj[Boolean], *), *, *]], ev1: Alternative[F]): F[T] = {
    val star = Star[(Disj[Boolean], *), A, B](a => (Disj(true), f(a)))

    self(star)(ev0).runStar(s) match {
      case (Disj(true), x) => ev1.pure(x)
      case (Disj(false), _) => ev1.empty
    }
  }

  /** convert a [[Traversal_]] to a [[proptics.internal.Bazaar]] */
  final def toBazaar: Bazaar[* => *, A, B, S, T] = self(new Bazaar[* => *, A, B, A, B] {
    override def runBazaar: RunBazaar[* => *, A, B, A, B] = new RunBazaar[* => *, A, B, A, B] {
      override def apply[F[_]](pafb: A => F[B])(s: A)(implicit ev: Applicative[F]): F[B] = pafb(s)
    }
  })

  /** transform a [[Traversal_]] to an [[ATraversal_]] */
  final def asATraversal: ATraversal_[S, T, A, B] =
    ATraversal_[S, T, A, B](new RunBazaar[* => *, A, B, S, T] {
      override def apply[F[_]](pafb: A => F[B])(s: S)(implicit ev: Applicative[F]): F[T] = self.traverse(s)(pafb)
    })

  /** convert a [[Traversal_]] to an [[IndexedTraversal_]] by using the integer positions as indices */
  final def zipWithIndex(implicit ev0: Applicative[State[Int, *]]): IndexedTraversal_[Int, S, T, A, B] =
    IndexedTraversal_.wander(new LensLikeWithIndex[Int, S, T, A, B] {
      override def apply[F[_]](f: ((A, Int)) => F[B])(implicit ev1: Applicative[F]): S => F[T] = s => {
        val state: State[Int, Unit] = State.apply[Int, Unit](i => (i, ()))
        val starNested: Star[Nested[State[Int, *], F, *], A, B] = Star { a =>
          val composed = (state.get, ev0.pure(a)).mapN((i, a) => f((a, i))) <* state.modify(_ + 1)

          Nested(composed)
        }

        self(starNested)
          .runStar(s)
          .value
          .runA(0)
          .value
      }
    })

  /** transform a [[Traversal_]] to a [[Fold_]] */
  final def asFold: Fold_[S, T, A, B] = new Fold_[S, T, A, B] {
    override private[proptics] def apply[R: Monoid](forget: Forget[R, A, B]): Forget[R, S, T] =
      Forget(self.foldMap(_)(forget.runForget))
  }

  /** convert a [[Traversal]] into a [[Lens]] over a list of the [[Traversal]]'s foci */
  final def unsafePartsOf(implicit ev0: Sellable[* => *, Bazaar[* => *, *, *, Unit, *]], ev1: Aux[* => *, State[List[B], *]]): Lens_[S, T, List[A], List[B]] =
    Bazaar.unsafePartsOf(self.toBazaar)

  /** compose this [[Traversal_]] with a function lifted to a [[Getter_]], having this [[Traversal_]] applied first */
  final def focus[C, D](f: A => C): Fold_[S, T, C, D] = andThen(Getter_[A, B, C, D](f))

  /** compose this [[Traversal_]] with an [[Iso_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: Iso_[A, B, C, D]): Traversal_[S, T, C, D] = new Traversal_[S, T, C, D] {
    override def apply[P[_, _]](pab: P[C, D])(implicit ev: Wander[P]): P[S, T] = self(other(pab))
  }

  /** compose this [[Traversal_]] with an [[Iso_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: Iso_[C, D, S, T]): Traversal_[C, D, A, B] = new Traversal_[C, D, A, B] {
    override private[proptics] def apply[P[_, _]](pab: P[A, B])(implicit ev: Wander[P]): P[C, D] = other(self(pab))
  }

  /** compose this [[Traversal_]] with an [[AnIso_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: AnIso_[A, B, C, D]): Traversal_[S, T, C, D] =
    wander(new LensLike[S, T, C, D] {
      override def apply[F[_]](f: C => F[D])(implicit ev: Applicative[F]): S => F[T] =
        self.overF(other.overF(f))
    })

  /** compose this [[Traversal_]] with an [[AnIso_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: AnIso_[C, D, S, T]): Traversal_[C, D, A, B] =
    wander(new LensLike[C, D, A, B] {
      override def apply[F[_]](f: A => F[B])(implicit ev: Applicative[F]): C => F[D] =
        other.overF(self.overF(f))
    })

  /** compose this [[Traversal_]] with a [[Lens_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: Lens_[A, B, C, D]): Traversal_[S, T, C, D] = new Traversal_[S, T, C, D] {
    override private[proptics] def apply[P[_, _]](pab: P[C, D])(implicit ev: Wander[P]): P[S, T] = self(other(pab))
  }

  /** compose this [[Traversal_]] with a [[Lens_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: Lens_[C, D, S, T]): Traversal_[C, D, A, B] = new Traversal_[C, D, A, B] {
    override private[proptics] def apply[P[_, _]](pab: P[A, B])(implicit ev: Wander[P]): P[C, D] = other(self(pab))
  }

  /** compose this [[Traversal_]] with an [[ALens_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: ALens_[A, B, C, D]): Traversal_[S, T, C, D] =
    wander(new LensLike[S, T, C, D] {
      override def apply[F[_]](f: C => F[D])(implicit ev: Applicative[F]): S => F[T] =
        self.traverse(_)(other.traverse(_)(f))
    })

  /** compose this [[Traversal_]] with an [[ALens_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: ALens_[C, D, S, T]): Traversal_[C, D, A, B] =
    wander(new LensLike[C, D, A, B] {
      override def apply[F[_]](f: A => F[B])(implicit ev: Applicative[F]): C => F[D] =
        other.overF(self.overF(f))
    })

  /** compose this [[Traversal_]] with a [[Prism_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: Prism_[A, B, C, D]): Traversal_[S, T, C, D] = new Traversal_[S, T, C, D] {
    override private[proptics] def apply[P[_, _]](pab: P[C, D])(implicit ev: Wander[P]): P[S, T] = self(other(pab))
  }

  /** compose this [[Traversal_]] with a [[Prism_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: Prism_[C, D, S, T]): Traversal_[C, D, A, B] = new Traversal_[C, D, A, B] {
    override private[proptics] def apply[P[_, _]](pab: P[A, B])(implicit ev: Wander[P]): P[C, D] = other(self(pab))
  }

  /** compose this [[Traversal_]] with an [[APrism_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: APrism_[A, B, C, D]): Traversal_[S, T, C, D] =
    wander(new LensLike[S, T, C, D] {
      override def apply[F[_]](f: C => F[D])(implicit ev: Applicative[F]): S => F[T] =
        self.traverse(_)(other.traverse(_)(f))
    })

  /** compose this [[Traversal_]] with an [[APrism_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: APrism_[C, D, S, T]): Traversal_[C, D, A, B] =
    wander(new LensLike[C, D, A, B] {
      override def apply[F[_]](f: A => F[B])(implicit ev: Applicative[F]): C => F[D] =
        other.overF(self.overF(f))
    })

  /** compose this [[Traversal_]] with an [[AffineTraversal_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: AffineTraversal_[A, B, C, D]): Traversal_[S, T, C, D] = new Traversal_[S, T, C, D] {
    override def apply[P[_, _]](pab: P[C, D])(implicit ev: Wander[P]): P[S, T] = self(other(pab))
  }

  /** compose this [[Traversal_]] with an [[AffineTraversal_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: AffineTraversal_[C, D, S, T]): Traversal_[C, D, A, B] = new Traversal_[C, D, A, B] {
    override private[proptics] def apply[P[_, _]](pab: P[A, B])(implicit ev: Wander[P]): P[C, D] = other(self(pab))
  }

  /** compose this [[Traversal_]] with an [[AnAffineTraversal_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: AnAffineTraversal_[A, B, C, D]): Traversal_[S, T, C, D] =
    wander(new LensLike[S, T, C, D] {
      override def apply[F[_]](f: C => F[D])(implicit ev: Applicative[F]): S => F[T] =
        self.overF(other.traverse(_)(f))
    })

  /** compose this [[Traversal_]] with an [[AnAffineTraversal_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: AnAffineTraversal_[C, D, S, T]): Traversal_[C, D, A, B] =
    wander(new LensLike[C, D, A, B] {
      override def apply[F[_]](f: A => F[B])(implicit ev: Applicative[F]): C => F[D] =
        other.overF(self.overF(f))
    })

  /** compose this [[Traversal_]] with a [[Traversal_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: Traversal_[A, B, C, D]): Traversal_[S, T, C, D] = new Traversal_[S, T, C, D] {
    override def apply[P[_, _]](pab: P[C, D])(implicit ev: Wander[P]): P[S, T] = self(other(pab))
  }

  /** compose this [[Traversal_]] with a [[Traversal_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: Traversal_[C, D, S, T]): Traversal_[C, D, A, B] = new Traversal_[C, D, A, B] {
    override private[proptics] def apply[P[_, _]](pab: P[A, B])(implicit ev: Wander[P]): P[C, D] = other(self(pab))
  }

  /** compose this [[Traversal_]] with an [[ATraversal_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: ATraversal_[A, B, C, D]): Traversal_[S, T, C, D] =
    wander(new LensLike[S, T, C, D] {
      override def apply[F[_]](f: C => F[D])(implicit ev: Applicative[F]): S => F[T] =
        self.overF(other.overF(f))
    })

  /** compose this [[Traversal_]] with an [[ATraversal_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: ATraversal_[C, D, S, T]): Traversal_[C, D, A, B] =
    wander(new LensLike[C, D, A, B] {
      override def apply[F[_]](f: A => F[B])(implicit ev: Applicative[F]): C => F[D] =
        other.overF(self.overF(f))
    })

  /** compose this [[Traversal_]] with a [[Setter_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: Setter_[A, B, C, D]): Setter_[S, T, C, D] = new Setter_[S, T, C, D] {
    override private[proptics] def apply(pab: C => D): S => T = self(other(pab))
  }

  /** compose this [[Traversal_]] with a [[Setter_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: Setter_[C, D, S, T]): Setter_[C, D, A, B] = new Setter_[C, D, A, B] {
    override private[proptics] def apply(pab: A => B): C => D = other(self(pab))
  }

  /** compose this [[Traversal_]] with a [[Getter_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: Getter_[A, B, C, D]): Fold_[S, T, C, D] = new Fold_[S, T, C, D] {
    override def apply[R: Monoid](forget: Forget[R, C, D]): Forget[R, S, T] =
      Forget(self.foldMap(_)(forget.runForget compose other.view))
  }

  /** compose this [[Traversal_]] with a [[Getter_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: Getter_[C, D, S, T]): Fold_[C, D, A, B] = new Fold_[C, D, A, B] {
    override private[proptics] def apply[R: Monoid](forget: Forget[R, A, B]): Forget[R, C, D] =
      Forget(c => self.foldMap(other.view(c))(forget.runForget))
  }

  /** compose this [[Traversal_]] with a [[Fold_]], having this [[Traversal_]] applied first */
  final def andThen[C, D](other: Fold_[A, B, C, D]): Fold_[S, T, C, D] = new Fold_[S, T, C, D] {
    override def apply[R: Monoid](forget: Forget[R, C, D]): Forget[R, S, T] = self(other(forget))
  }

  /** compose this [[Traversal_]] with a [[Fold_]], having this [[Traversal_]] applied last */
  final def compose[C, D](other: Fold_[C, D, S, T]): Fold_[C, D, A, B] = new Fold_[C, D, A, B] {
    override private[proptics] def apply[R: Monoid](forget: Forget[R, A, B]): Forget[R, C, D] = other(self(forget))
  }

  /** compose this [[Traversal_]] with an [[IndexedLens_]], having this [[Traversal_]] applied first */
  final def andThen[I, C, D](other: IndexedLens_[I, A, B, C, D]): IndexedTraversal_[I, S, T, C, D] =
    IndexedTraversal_.wander(new LensLikeWithIndex[I, S, T, C, D] {
      override def apply[F[_]](f: ((C, I)) => F[D])(implicit ev: Applicative[F]): S => F[T] =
        self.traverse(_)(other.traverse(_)(f))
    })

  /** compose this [[Traversal_]] with an [[IndexedLens_]], having this [[Traversal_]] applied last */
  final def compose[I, C, D](other: IndexedLens_[I, C, D, S, T]): IndexedTraversal_[I, C, D, A, B] =
    IndexedTraversal_.wander(new LensLikeWithIndex[I, C, D, A, B] {
      override def apply[F[_]](f: ((A, I)) => F[B])(implicit ev: Applicative[F]): C => F[D] =
        other.overF { case (s, i) => self.traverse(s)(a => f((a, i))) }
    })

  /** compose this [[Traversal_]] with an [[AnIndexedLens_]], having this [[Traversal_]] applied first */
  final def andThen[I, C, D](other: AnIndexedLens_[I, A, B, C, D]): IndexedTraversal_[I, S, T, C, D] =
    IndexedTraversal_.wander(new LensLikeWithIndex[I, S, T, C, D] {
      override def apply[F[_]](f: ((C, I)) => F[D])(implicit ev: Applicative[F]): S => F[T] =
        self.traverse(_)(other.traverse(_)(f))
    })

  /** compose this [[Traversal_]] with an [[AnIndexedLens_]], having this [[Traversal_]] applied last */
  final def compose[I, C, D](other: AnIndexedLens_[I, C, D, S, T]): IndexedTraversal_[I, C, D, A, B] =
    IndexedTraversal_.wander(new LensLikeWithIndex[I, C, D, A, B] {
      override def apply[F[_]](f: ((A, I)) => F[B])(implicit ev: Applicative[F]): C => F[D] =
        other.overF { case (s, i) => self.traverse(s)(a => f((a, i))) }
    })

  /** compose this [[Traversal_]] with an [[IndexedTraversal_]], having this [[Traversal_]] applied first */
  final def andThen[I, C, D](other: IndexedTraversal_[I, A, B, C, D]): IndexedTraversal_[I, S, T, C, D] =
    IndexedTraversal_.wander(new LensLikeWithIndex[I, S, T, C, D] {
      override def apply[F[_]](f: ((C, I)) => F[D])(implicit ev: Applicative[F]): S => F[T] =
        self.traverse(_)(other.traverse(_)(f))
    })

  /** compose this [[Traversal_]] with an [[IndexedTraversal_]], having this [[Traversal_]] applied last */
  final def compose[I, C, D](other: IndexedTraversal_[I, C, D, S, T]): IndexedTraversal_[I, C, D, A, B] =
    IndexedTraversal_.wander(new LensLikeWithIndex[I, C, D, A, B] {
      override def apply[F[_]](f: ((A, I)) => F[B])(implicit ev: Applicative[F]): C => F[D] =
        other.overF { case (s, i) => self.traverse(s)(a => f((a, i))) }
    })

  /** compose this [[Traversal_]] with an [[IndexedSetter_]], having this [[Traversal_]] applied first */
  final def andThen[I, C, D](other: IndexedSetter_[I, A, B, C, D]): IndexedSetter_[I, S, T, C, D] = new IndexedSetter_[I, S, T, C, D] {
    override private[proptics] def apply(indexed: Indexed[* => *, I, C, D]): S => T =
      self.over(other.over(indexed.runIndex))
  }

  /** compose this [[Traversal_]] with an [[IndexedSetter_]], having this [[Traversal_]] applied last */
  final def compose[I, C, D](other: IndexedSetter_[I, C, D, S, T]): IndexedSetter_[I, C, D, A, B] = new IndexedSetter_[I, C, D, A, B] {
    override private[proptics] def apply(indexed: Indexed[Function, I, A, B]): C => D =
      other.over { case (s, i) => self.over(a => indexed.runIndex((a, i)))(s) }
  }

  /** compose this [[Traversal_]] with an [[IndexedGetter_]], having this [[Traversal_]] applied first */
  final def andThen[I, C, D](other: IndexedGetter_[I, A, B, C, D]): IndexedFold_[I, S, T, C, D] = new IndexedFold_[I, S, T, C, D] {
    override private[proptics] def apply[R: Monoid](indexed: Indexed[Forget[R, *, *], I, C, D]): Forget[R, S, T] =
      Forget(self.foldMap(_)(indexed.runIndex.runForget compose other.view))
  }

  /** compose this [[Traversal_]] with an [[IndexedGetter_]], having this [[Traversal_]] applied last */
  final def compose[I, C, D](other: IndexedGetter_[I, C, D, S, T]): IndexedFold_[I, C, D, A, B] = new IndexedFold_[I, C, D, A, B] {
    override private[proptics] def apply[R: Monoid](indexed: Indexed[Forget[R, *, *], I, A, B]): Forget[R, C, D] =
      Forget { c =>
        val (s, i) = other.view(c)
        self.foldMap(s)(a => indexed.runIndex.runForget((a, i)))
      }
  }

  /** compose this [[Traversal_]] with an [[IndexedFold_]], having this [[Traversal_]] applied first */
  final def andThen[I, C, D](other: IndexedFold_[I, A, B, C, D]): IndexedFold_[I, S, T, C, D] = new IndexedFold_[I, S, T, C, D] {
    override private[proptics] def apply[R: Monoid](indexed: Indexed[Forget[R, *, *], I, C, D]): Forget[R, S, T] =
      Forget(self.foldMap(_)(other.foldMap(_)(indexed.runIndex.runForget)))
  }

  /** compose this [[Traversal_]] with an [[IndexedFold_]], having this [[Traversal_]] applied last */
  final def compose[I, C, D](other: IndexedFold_[I, C, D, S, T]): IndexedFold_[I, C, D, A, B] = new IndexedFold_[I, C, D, A, B] {
    override private[proptics] def apply[R: Monoid](indexed: Indexed[Forget[R, *, *], I, A, B]): Forget[R, C, D] =
      Forget(other.foldMap(_) { case (s, i) => self.foldMap(s)(a => indexed.runIndex.runForget((a, i))) })
  }
}

object Traversal_ {
  /** create a polymorphic [[Traversal_]] from Rank2TypeTraversalLike encoding */
  private[proptics] def apply[S, T, A, B](lensLikeTraversal: Rank2TypeTraversalLike[S, T, A, B]): Traversal_[S, T, A, B] = new Traversal_[S, T, A, B] {
    override def apply[P[_, _]](pab: P[A, B])(implicit ev0: Wander[P]): P[S, T] = lensLikeTraversal(pab)
  }

  /** create a polymorphic [[Traversal_]] from a getter/setter pair */
  final def apply[S, T, A, B](get: S => A)(_set: S => B => T): Traversal_[S, T, A, B] = new Traversal_[S, T, A, B] {
    override def apply[P[_, _]](pab: P[A, B])(implicit ev: Wander[P]): P[S, T] = {
      val traversing = new Traversing[S, T, A, B] {
        override def apply[F[_]](f: A => F[B])(s: S)(implicit ev: Applicative[F]): F[T] = ev.map(f(get(s)))(_set(s))
      }

      ev.wander(traversing)(pab)
    }
  }

  /** create a polymorphic [[Traversal_]] from a combined getter/setter */
  final def traversal[S, T, A, B](to: S => (A, B => T)): Traversal_[S, T, A, B] = Traversal_(new Rank2TypeTraversalLike[S, T, A, B] {
    override def apply[P[_, _]](pab: P[A, B])(implicit ev: Wander[P]): P[S, T] = liftOptic(to)(ev)(pab)
  })

  /** traverse elements of a [[Traversal_]] that satisfy a predicate */
  final def filter[A](predicate: A => Boolean): Traversal_[A, A, A, A] =
    Traversal_[A, A, A, A](new Rank2TypeTraversalLike[A, A, A, A] {
      override def apply[P[_, _]](pab: P[A, A])(implicit ev0: Wander[P]): P[A, A] = {
        val traversing = new Traversing[A, A, A, A] {
          override def apply[F[_]](f: A => F[A])(s: A)(implicit ev1: Applicative[F]): F[A] =
            if (predicate(s)) f(s) else ev1.pure(s)
        }

        ev0.wander(traversing)(pab)
      }
    })

  /** create a polymorphic [[Traversal_]] from Traverse */
  final def fromTraverse[G[_], A, B](implicit ev0: Traverse[G]): Traversal_[G[A], G[B], A, B] = Traversal_(new Rank2TypeTraversalLike[G[A], G[B], A, B] {
    override def apply[P[_, _]](pab: P[A, B])(implicit ev1: Wander[P]): P[G[A], G[B]] = {
      val traversing = new Traversing[G[A], G[B], A, B] {
        override def apply[F[_]](f: A => F[B])(s: G[A])(implicit ev2: Applicative[F]): F[G[B]] =
          ev0.traverse[F, A, B](s)(f)
      }

      ev1.wander(traversing)(pab)
    }
  })

  /** create a polymorphic [[Traversal_]] from [[proptics.internal.Bazaar]] */
  final def fromBazaar[S, T, A, B](bazaar: Bazaar[* => *, A, B, S, T]): Traversal_[S, T, A, B] =
    Traversal_[S, T, A, B](new Rank2TypeTraversalLike[S, T, A, B] {
      override def apply[P[_, _]](pab: P[A, B])(implicit ev: Wander[P]): P[S, T] = {
        val traversing = new Traversing[S, T, A, B] {
          override def apply[F[_]](f: A => F[B])(s: S)(implicit ev: Applicative[F]): F[T] = bazaar.runBazaar(f)(s)
        }

        ev.wander(traversing)(pab)
      }
    })

  /** traverse both parts of a [[cats.Bitraverse]] with matching types */
  final def both[G[_, _]: Bitraverse, A, B]: Traversal_[G[A, A], G[B, B], A, B] =
    Traversal_(new Rank2TypeTraversalLike[G[A, A], G[B, B], A, B] {
      override def apply[P[_, _]](pab: P[A, B])(implicit ev: Wander[P]): P[G[A, A], G[B, B]] = {
        val traversing = new Traversing[G[A, A], G[B, B], A, B] {
          override def apply[F[_]](f: A => F[B])(s: G[A, A])(implicit ev: Applicative[F]): F[G[B, B]] =
            s.bitraverse(f, f)
        }

        ev.wander(traversing)(pab)
      }
    })

  /** create a polymorphic [[Traversal_]] from a rank 2 type traversal function */
  final def wander[S, T, A, B](lensLike: LensLike[S, T, A, B]): Traversal_[S, T, A, B] =
    Traversal_(new Rank2TypeTraversalLike[S, T, A, B] {
      override def apply[P[_, _]](pab: P[A, B])(implicit ev0: Wander[P]): P[S, T] = {
        def traversing: Traversing[S, T, A, B] = new Traversing[S, T, A, B] {
          override def apply[F[_]](f: A => F[B])(s: S)(implicit ev1: Applicative[F]): F[T] = lensLike[F](f)(ev1)(s)
        }

        ev0.wander(traversing)(pab)
      }
    })

  /** polymorphic identity of a [[Traversal_]] */
  final def id[S, T]: Traversal_[S, T, S, T] = Traversal_(identity[S] _)(const(identity[T]))

  /** convert a [[Traversal]] into a [[Lens]] over a list of the [[Traversal]]'s foci */
  final def unsafePartsOf[S, T, A, B](
      traversal: Traversal_[S, T, A, B])(implicit ev0: Sellable[* => *, Bazaar[* => *, *, *, Unit, *]], ev2: Aux[* => *, State[List[B], *]]): Lens_[S, T, List[A], List[B]] =
    traversal.unsafePartsOf
}

object Traversal {
  /** create a monomorphic [[Traversal]] from Rank2TypeTraversalLike encoding */
  final def fromTraversal[S, A](lensLikeTraversal: Rank2TypeTraversalLike[S, S, A, A]): Traversal[S, A] =
    Traversal_[S, S, A, A](lensLikeTraversal)

  /** create a monomorphic [[Traversal]] from a getter/setter pair */
  final def apply[S, A](get: S => A)(set: S => A => S): Traversal[S, A] = Traversal_(get)(set)

  /** create a monomorphic [[Traversal]] from a combined getter/setter */
  final def traversal[S, A](to: S => (A, A => S)): Traversal[S, A] = Traversal_.traversal(to)

  /** traverse elements of a [[Traversal]], that satisfy a predicate */
  final def filter[A](predicate: A => Boolean): Traversal[A, A] = Traversal_.filter(predicate)

  /** traverse elements of a [[Traversal]], by taking the first element of a [[Fold]] and using it as a filter */
  final def filter[A, B](fold: Fold[A, B]): Traversal[A, A] =
    Traversal_[A, A, A, A](new Rank2TypeTraversalLike[A, A, A, A] {
      override def apply[P[_, _]](pab: P[A, A])(implicit ev0: Wander[P]): P[A, A] = {
        val traversing = new Traversing[A, A, A, A] {
          override def apply[F[_]](f: A => F[A])(s: A)(implicit ev1: Applicative[F]): F[A] =
            fold.preview(s).fold(ev1.pure(s))(const(f(s)))
        }

        ev0.wander(traversing)(pab)
      }
    })

  /** create a monomorphic [[Traversal]] from a [[cats.Traverse]] */
  final def fromTraverse[F[_]: Traverse, A]: Traversal[F[A], A] = Traversal_.fromTraverse

  /** create a monomorphic [[Traversal]] from a [[proptics.internal.Bazaar]] */
  final def fromBazaar[S, A](bazaar: Bazaar[* => *, A, A, S, S]): Traversal[S, A] = Traversal_.fromBazaar(bazaar)

  /** traverse both parts of a [[cats.Bitraverse]] with matching types */
  final def both[G[_, _]: Bitraverse, A]: Traversal[G[A, A], A] = Traversal_.both[G, A, A]

  /** create a monomorphic [[Traversal]] from a rank 2 type traversal function */
  final def wander[S, A](lensLike: LensLike[S, S, A, A]): Traversal[S, A] =
    Traversal_.wander[S, S, A, A](lensLike)

  /** monomorphic identity of a [[Traversal]] */
  final def id[S]: Traversal[S, S] = Traversal_.id[S, S]

  /** create a monomorphic [[Traversal]] that narrows the focus to a single element */
  final def single[F[_]: Traverse, A](i: Int): Traversal[F[A], A] = Traversal.fromTraverse[F, A].single(i)

  /** create a monomorphic [[Traversal]] that selects the first n elements of a Traverse */
  final def take[F[_]: Traverse, A](i: Int): Traversal[F[A], A] = Traversal.fromTraverse[F, A].take(i)

  /** create a monomorphic [[Traversal]] that selects all elements of a Traverse except the first n ones */
  final def drop[F[_]: Traverse, A](i: Int): Traversal[F[A], A] = Traversal.fromTraverse[F, A].drop(i)

  /** create a monomorphic [[Traversal]] that takes the longest prefix of elements of a Traverse that satisfy a predicate */
  final def takeWhile[G[_]: Traverse, A](predicate: A => Boolean): Traversal[G[A], A] =
    Traversal.fromTraverse[G, A].takeWhile(predicate)

  /** create a monomorphic [[Traversal]] that drop longest prefix of elements of a Traverse that satisfy a predicate */
  final def dropWhile[G[_]: Traverse, A](predicate: A => Boolean): Traversal[G[A], A] =
    Traversal.fromTraverse[G, A].dropWhile(predicate)

  /** convert a [[Traversal]] into a [[Lens]] over a list of the [[Traversal]]'s foci */
  final def partsOf[S, T, A](traversal: Traversal_[S, T, A, A])(implicit ev0: Sellable[* => *, Bazaar[* => *, *, *, Unit, *]]): Lens_[S, T, List[A], List[A]] =
    Bazaar.partsOf(traversal.toBazaar)
}

object Traversal2 {
  /** create a polymorphic [[Traversal_]] using two view functions that accept the same structure, and a setter function, and simultaneously focus on two distinct parts of it
    */
  def apply[S, T, A, B](view1: S => A, view2: S => A)(set: (B, B, S) => T): Traversal_[S, T, A, B] =
    Traversal_.wander(new LensLike[S, T, A, B] {
      override def apply[F[_]](f: A => F[B])(implicit ev: Applicative[F]): S => F[T] = s => ev.map2(f(view1(s)), f(view2(s)))(set(_, _, s))
    })
}

object Traversal3 {
  /** create a polymorphic [[Traversal_]] using three view functions that accept the same structure, and a setter function, and simultaneously focus on three distinct parts of it
    */
  def apply[S, T, A, B](view1: S => A, view2: S => A, view3: S => A)(set: (B, B, B, S) => T): Traversal_[S, T, A, B] =
    Traversal_.wander(new LensLike[S, T, A, B] {
      override def apply[F[_]](f: A => F[B])(implicit ev: Applicative[F]): S => F[T] = s => ev.map3(f(view1(s)), f(view2(s)), f(view3(s)))(set(_, _, _, s))
    })
}

object Traversal4 {
  /** create a polymorphic [[Traversal_]] using four view functions that accept the same structure, and a setter function, and simultaneously focus on four distinct parts of it
    */
  def apply[S, T, A, B](view1: S => A, view2: S => A, view3: S => A, view4: S => A)(set: (B, B, B, B, S) => T): Traversal_[S, T, A, B] =
    Traversal_.wander(new LensLike[S, T, A, B] {
      override def apply[F[_]](f: A => F[B])(implicit ev: Applicative[F]): S => F[T] = s => ev.map4(f(view1(s)), f(view2(s)), f(view3(s)), f(view4(s)))(set(_, _, _, _, s))
    })
}

object Traversal5 {
  /** create a polymorphic [[Traversal_]] using five view functions that accept the same structure, and a setter function, and simultaneously focus on five distinct parts of it
    */
  def apply[S, T, A, B](view1: S => A, view2: S => A, view3: S => A, view4: S => A, view5: S => A)(set: (B, B, B, B, B, S) => T): Traversal_[S, T, A, B] =
    Traversal_.wander(new LensLike[S, T, A, B] {
      override def apply[F[_]](f: A => F[B])(implicit ev: Applicative[F]): S => F[T] =
        s => ev.map5(f(view1(s)), f(view2(s)), f(view3(s)), f(view4(s)), f(view5(s)))(set(_, _, _, _, _, s))
    })
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy