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

proptics.syntax.applied.AppliedFoldSyntax.scala Maven / Gradle / Ivy

package proptics.syntax.applied

import scala.reflect.ClassTag

import cats.data.{NonEmptyList, State}
import cats.{Applicative, Bifoldable, Eq, Foldable, Traverse}

import proptics._
import proptics.applied.{AppliedFold, AppliedFold_}
import proptics.std.list._
import proptics.std.string.{takeWords => tkWords, _}
import proptics.syntax.fold._

trait AppliedFoldSyntax {
  implicit final def appliedFoldOpsWithFoldable[F[_], A](s: F[A]): AppliedFoldOpsWithFoldable[F, A] = AppliedFoldOpsWithFoldable(s)

  implicit final def appliedFoldElementOps[S, T, A](appliedFold: AppliedFold_[S, T, A, A]): AppliedFoldElementOps[S, T, A] = AppliedFoldElementOps(appliedFold)

  implicit final def appliedFoldWithFoldableFocusElementOps[F[_], S, T, A](appliedFold: AppliedFold_[S, T, F[A], F[A]]): AppliedFoldWithFoldableFocusElementOps[F, S, T, A] =
    AppliedFoldWithFoldableFocusElementOps(appliedFold)

  implicit final def appliedFoldListOps[S, A](appliedFold: AppliedFold[S, List[A]]): AppliedFoldListOps[S, A] = AppliedFoldListOps(appliedFold)

  implicit final def appliedFoldStringOps[S](appliedFold: AppliedFold[S, String]): AppliedFoldStringOps[S] = AppliedFoldStringOps(appliedFold)

  implicit final def appliedBifoldablelElementOps[G[_, _], A](s: G[A, A]): AppliedBifoldableElementOps[G, A] = AppliedBifoldableElementOps(s)
}

final case class AppliedFoldOpsWithFoldable[F[_], A](private val s: F[A]) extends AnyVal {
  /** create a polymorphic [[AppliedFold_]] from [[cats.Foldable]] */
  def foldable_[B](implicit ev: Foldable[F]): AppliedFold_[F[A], F[B], A, B] =
    AppliedFold_(s, Fold_.fromFoldable[F, A, B])

  /** create a monomorphic [[AppliedFold]] from [[cats.Foldable]] */
  def foldable(implicit ev: Foldable[F]): AppliedFold[F[A], A] =
    AppliedFold(s, Fold.fromFoldable[F, A])
}

final case class AppliedFoldElementOps[S, T, A](private val appliedFold: AppliedFold_[S, T, A, A]) extends AnyVal {
  def value: S = appliedFold.value
  def optic: Fold_[S, T, A, A] = appliedFold.optic

  /** narrow the focus of a [[Fold_]] focus a single element */
  def single(i: Int): AppliedFold_[S, T, A, A] = AppliedFold_(value, optic.single(i))

  /** traverse elements of a [[Fold_]] whose index satisfy a predicate */
  def filterByIndex(predicate: Int => Boolean): AppliedFold_[S, T, A, A] =
    AppliedFold_(value, optic.filterByIndex(predicate))

  /** select the first n elements of a [[Fold_]] */
  def take(i: Int): AppliedFold_[S, T, A, A] = AppliedFold_(value, optic.take(i))

  /** select all elements of a [[Fold_]] except first n ones */
  def drop(i: Int): AppliedFold_[S, T, A, A] = AppliedFold_(value, optic.drop(i))

  /** take longest prefix of elements of a [[Fold_]] that satisfy a predicate */
  def takeWhile(predicate: A => Boolean)(implicit ev0: Applicative[State[Boolean, *]]): AppliedFold_[S, T, A, A] =
    AppliedFold_(value, optic.takeWhile(predicate))

  /** drop longest prefix of elements of a [[Fold_]] that satisfy a predicate */
  def dropWhile(predicate: A => Boolean)(implicit ev0: Applicative[State[Boolean, *]]): AppliedFold_[S, T, A, A] =
    AppliedFold_(value, optic.dropWhile(predicate))

  /** filter out elements that do not match the predicate, of optics composed with this [[Fold_]] */
  def filter(predicate: A => Boolean): AppliedFold_[S, T, A, A] =
    AppliedFold_(value, optic.andThen(Fold.filter[A](predicate)))

  /** filter out elements that match the predicate, of optics composed with this [[Fold]] */
  def filterNot(predicate: A => Boolean): AppliedFold_[S, T, A, A] =
    filter(a => !predicate(a))

  /** filter out elements using a [[Fold]], of optics composed with this [[Fold]] */
  def filterF[B](fold: Fold[A, B]): AppliedFold_[S, T, A, A] =
    AppliedFold_(value, optic.andThen(Fold.filter[A, B](fold)))

  /** filter out elements using an [[AffineTraversal]], of optics composed with this [[Fold]] */
  def filterF[B](fold: AffineTraversal[A, B]): AppliedFold_[S, T, A, A] =
    AppliedFold_(value, optic.andThen(Fold.filter[A, B](fold)))

  /** filter out elements using a [[Fold]], of optics composed with this [[Fold]] */
  def onlyWhen[B: Eq](f: A => B, is: B): AppliedFold_[S, T, A, A] = {
    val foldPredicate = Fold(f).andThen(Prism.only[B](is))

    AppliedFold_(appliedFold.value, appliedFold.optic.andThen(Fold.filter(foldPredicate)))
  }
}

final case class AppliedFoldWithFoldableFocusElementOps[F[_], S, T, A](private val appliedFold: AppliedFold_[S, T, F[A], F[A]]) extends AnyVal {
  def value: S = appliedFold.value
  def optic: Fold_[S, T, F[A], F[A]] = appliedFold.optic

  /** select the first n elements of a [[Fold]] */
  def take(i: Int)(implicit ev: Foldable[F]): AppliedFold_[S, T, A, A] =
    AppliedFold_(value, optic.andThen(Fold.take[F, A](i)))

  /** select all elements of a [[Fold]] except first n ones */
  def drop(i: Int)(implicit ev: Traverse[F]): AppliedFold_[S, T, A, A] =
    AppliedFold_(value, optic.andThen(Fold.drop[F, A](i)))

  /** take longest prefix of elements of a [[Fold]] that satisfy a predicate */
  def takeWhile(predicate: A => Boolean)(implicit ev0: Applicative[State[Boolean, *]], ev1: Foldable[F]): AppliedFold_[S, T, A, A] =
    AppliedFold_(value, optic.andThen(Fold.takeWhile[F, A](predicate)))

  /** drop longest prefix of elements of a [[Fold]] that satisfy a predicate */
  def dropWhile(predicate: A => Boolean)(implicit ev0: Applicative[State[Boolean, *]], ev1: Foldable[F]): AppliedFold_[S, T, A, A] =
    AppliedFold_(value, optic.andThen(Fold.dropWhile[F, A](predicate)))

  /** compose this [[Fold]] with a [[Fold]], having this [[Fold]] applied first */
  def andThenFold(implicit ev: Foldable[F]): AppliedFold_[S, T, A, A] =
    AppliedFold_(value, optic.andThen(Fold.fromFoldable[F, A]))

  /** compose this [[Fold]] with a [[Traversal]], having this [[Fold]] applied first */
  def andThenTraverse(implicit ev: Traverse[F]): AppliedFold_[S, T, A, A] =
    AppliedFold_(value, optic.andThen(Traversal.fromTraverse[F, A]))
}

final case class AppliedFoldListOps[S, A](private val appliedFold: AppliedFold[S, List[A]]) extends AnyVal {
  /** convert from a [[List[A]]] to a [[Vector[A]] */
  def toVector: AppliedFold[S, Vector[A]] = appliedFold.andThen(listToVector[A])

  /** convert from a [[List[A]]] to a [[Array[A]] */
  def toArray(implicit ev: ClassTag[A]): AppliedFold[S, Array[A]] = appliedFold.andThen(listToArray[A])

  /** convert from a [[List[A]]] to a [[NonEmptyList[A]] */
  def toNel: AppliedFold[S, NonEmptyList[A]] = appliedFold.andThen(listToNonEmptyList[A])
}

final case class AppliedFoldListOfCharsOps[S](private val appliedFold: AppliedFold[S, List[Char]]) extends AnyVal {
  /** convert from a [[List[char]]] to a [[String]] */
  def mkString: AppliedFold[S, String] = appliedFold.andThen(charsToString)
}

final case class AppliedFoldStringOps[S](private val appliedFold: AppliedFold[S, String]) extends AnyVal {
  /** convert from a [[List[char]]] to a [[String]] */
  def toChars: AppliedFold[S, List[Char]] = appliedFold.andThen(stringToChars)

  /** fold over the individual words of a String */
  def toWords: AppliedFold[S, String] = appliedFold.andThen(words)

  /** select the first n words of a string */
  def takeWords(i: Int): AppliedFold[S, String] = appliedFold.andThen(tkWords(i))
}

final case class AppliedBifoldableElementOps[G[_, _], A](private val s: G[A, A]) extends AnyVal {
  /** create a polymorphic [[Fold_]] from [[cats.Bifoldable]] */
  def bifold_[B](implicit ev: Bifoldable[G]): AppliedFold_[G[A, A], G[B, B], A, B] = AppliedFold_(s, Fold_.both[G, A, B])

  /** create a monomorphic [[Fold]] from [[cats.Bifoldable]] */
  def bifold(implicit ev: Bifoldable[G]): AppliedFold[G[A, A], A] = AppliedFold(s, Fold.both[G, A])
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy