Skip to content

Commit

Permalink
add inheritance for applied optics (#1116)
Browse files Browse the repository at this point in the history
  • Loading branch information
julien-truffaut authored Mar 8, 2021
1 parent d1c1746 commit 002990e
Show file tree
Hide file tree
Showing 9 changed files with 551 additions and 462 deletions.
22 changes: 11 additions & 11 deletions core/shared/src/main/scala/monocle/syntax/Applied.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,33 @@ object applied extends AppliedSyntax

trait AppliedSyntax {
implicit def toAppliedFoldOps[S](value: S): AppliedFoldOps[S] =
new AppliedFoldOps(value)
AppliedFoldOps(value)
implicit def toAppliedGetterOps[S](value: S): AppliedGetterOps[S] =
new AppliedGetterOps(value)
AppliedGetterOps(value)
implicit def toAppliedIsoOps[S](value: S): AppliedIsoOps[S] =
new AppliedIsoOps(value)
AppliedIsoOps(value)
implicit def toAppliedLensOps[S](value: S): AppliedLensOps[S] =
new AppliedLensOps(value)
AppliedLensOps(value)
implicit def toAppliedOptionalOps[S](value: S): AppliedOptionalOps[S] =
new AppliedOptionalOps(value)
AppliedOptionalOps(value)
implicit def toAppliedPrismOps[S](value: S): AppliedPrismOps[S] =
new AppliedPrismOps(value)
AppliedPrismOps(value)
implicit def toAppliedSetterOps[S](value: S): AppliedSetterOps[S] =
new AppliedSetterOps(value)
AppliedSetterOps(value)
implicit def toAppliedTraversalOps[S](value: S): AppliedTraversalOps[S] =
new AppliedTraversalOps(value)
AppliedTraversalOps(value)
}

final case class AppliedFoldOps[S](private val s: S) extends AnyVal {
@deprecated("use focus().andThen", since = "3.0.0-M1")
def applyFold[A](fold: Fold[S, A]): AppliedFold[S, A] =
new AppliedFold[S, A](s, fold)
AppliedFold[S, A](s, fold)
}

final case class AppliedGetterOps[S](private val s: S) extends AnyVal {
@deprecated("use focus().andThen", since = "3.0.0-M1")
def applyGetter[A](getter: Getter[S, A]): AppliedGetter[S, A] =
new AppliedGetter[S, A](s, getter)
AppliedGetter[S, A](s, getter)
}

final case class AppliedIsoOps[S](private val s: S) extends AnyVal {
Expand Down Expand Up @@ -85,7 +85,7 @@ final case class AppliedPrismOps[S](private val s: S) extends AnyVal {
final case class AppliedSetterOps[S](private val s: S) extends AnyVal {
@deprecated("use focus().andThen", since = "3.0.0-M1")
def applySetter[T, A, B](setter: PSetter[S, T, A, B]): AppliedPSetter[S, T, A, B] =
new AppliedPSetter[S, T, A, B](s, setter)
AppliedPSetter[S, T, A, B](s, setter)
}

final case class AppliedTraversalOps[S](private val s: S) extends AnyVal {
Expand Down
133 changes: 81 additions & 52 deletions core/shared/src/main/scala/monocle/syntax/AppliedFold.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,95 +2,124 @@ package monocle.syntax

import cats.Monoid
import monocle.function.{At, Each, FilterIndex, Index}
import monocle.{std, Fold, Getter, Optional, PIso, PLens, POptional, PPrism, PTraversal}
import monocle._

case class AppliedFold[S, A](s: S, _fold: Fold[S, A]) {
def foldMap[M: Monoid](f: A => M): M = _fold.foldMap(f)(s)
trait AppliedFold[S, A] {
def value: S
def optic: Fold[S, A]

def getAll: List[A] = _fold.getAll(s)
def find(p: A => Boolean): Option[A] = _fold.find(p)(s)
def headOption: Option[A] = _fold.headOption(s)
def lastOption: Option[A] = _fold.lastOption(s)
def exist(p: A => Boolean): Boolean = _fold.exist(p)(s)
def all(p: A => Boolean): Boolean = _fold.all(p)(s)
def length: Int = _fold.length(s)
def isEmpty: Boolean = _fold.isEmpty(s)
def nonEmpty: Boolean = _fold.nonEmpty(s)
def foldMap[M: Monoid](f: A => M): M = optic.foldMap(f)(value)

def getAll: List[A] = optic.getAll(value)
def find(p: A => Boolean): Option[A] = optic.find(p)(value)
def headOption: Option[A] = optic.headOption(value)
def lastOption: Option[A] = optic.lastOption(value)
def exist(p: A => Boolean): Boolean = optic.exist(p)(value)
def all(p: A => Boolean): Boolean = optic.all(p)(value)
def length: Int = optic.length(value)
def isEmpty: Boolean = optic.isEmpty(value)
def nonEmpty: Boolean = optic.nonEmpty(value)

def some[A1](implicit ev1: A =:= Option[A1]): AppliedFold[S, A1] =
adapt[Option[A1]].andThen(std.option.some[A1])

private[monocle] def adapt[A1](implicit evA: A =:= A1): AppliedFold[S, A1] =
evA.substituteCo[AppliedFold[S, *]](this)

def andThen[B](other: Fold[A, B]): AppliedFold[S, B] =
AppliedFold(value, optic.andThen(other))
}

object AppliedFold {
def apply[S, A](_value: S, _optic: Fold[S, A]): AppliedFold[S, A] =
new AppliedFold[S, A] {
val value: S = _value
val optic: Fold[S, A] = _optic
}

implicit def appliedFoldSyntax[S, A](self: AppliedFold[S, A]): AppliedFoldSyntax[S, A] =
new AppliedFoldSyntax(self)
}

final case class AppliedFoldSyntax[S, A](private val self: AppliedFold[S, A]) extends AnyVal {
def each[C](implicit evEach: Each[A, C]): AppliedFold[S, C] =
andThen(evEach.each)
self.andThen(evEach.each)

/** Select all the elements which satisfies the predicate.
* This combinator can break the fusion property see Optional.filter for more details.
*/
def filter(predicate: A => Boolean): AppliedFold[S, A] =
andThen(Optional.filter(predicate))
self.andThen(Optional.filter(predicate))

def filterIndex[I, A1](predicate: I => Boolean)(implicit ev: FilterIndex[A, I, A1]): AppliedFold[S, A1] =
andThen(ev.filterIndex(predicate))
self.andThen(ev.filterIndex(predicate))

def some[A1](implicit ev1: A =:= Option[A1]): AppliedFold[S, A1] =
adapt[Option[A1]].andThen(std.option.some[A1])

def withDefault[A1](defaultValue: A1)(implicit ev1: A =:= Option[A1]): AppliedFold[S, A1] =
adapt[Option[A1]].andThen(std.option.withDefault(defaultValue))
def withDefault[A1](defaultValue: A1)(implicit evOpt: A =:= Option[A1]): AppliedFold[S, A1] =
self.adapt[Option[A1]].andThen(std.option.withDefault(defaultValue))

def at[I, A1](i: I)(implicit evAt: At[A, i.type, A1]): AppliedFold[S, A1] =
andThen(evAt.at(i))
self.andThen(evAt.at(i))

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): AppliedFold[S, A1] =
andThen(evIndex.index(i))

private def adapt[A1](implicit evA: A =:= A1): AppliedFold[S, A1] =
evA.substituteCo[AppliedFold[S, *]](this)

def andThen[B](other: Fold[A, B]): AppliedFold[S, B] =
AppliedFold(s, _fold.andThen(other))
def andThen[B](other: Getter[A, B]): AppliedFold[S, B] =
AppliedFold(s, _fold.andThen(other))
def andThen[B, C, D](other: PTraversal[A, B, C, D]): AppliedFold[S, C] =
AppliedFold(s, _fold.andThen(other))
def andThen[B, C, D](other: POptional[A, B, C, D]): AppliedFold[S, C] =
AppliedFold(s, _fold.andThen(other))
def andThen[B, C, D](other: PPrism[A, B, C, D]): AppliedFold[S, C] =
AppliedFold(s, _fold.andThen(other))
def andThen[B, C, D](other: PLens[A, B, C, D]): AppliedFold[S, C] =
AppliedFold(s, _fold.andThen(other))
def andThen[B, C, D](other: PIso[A, B, C, D]): AppliedFold[S, C] =
AppliedFold(s, _fold.andThen(other))
self.andThen(evIndex.index(i))

/** compose a [[Fold]] with a [[Fold]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeFold[B](other: Fold[A, B]): AppliedFold[S, B] = andThen(other)
def composeFold[C](other: Fold[A, C]): AppliedFold[S, C] =
self.andThen(other)

/** compose a [[Fold]] with a [[Getter]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeGetter[B](other: Getter[A, B]): AppliedFold[S, B] = andThen(other)
def composeGetter[C](other: Getter[A, C]): AppliedFold[S, C] =
self.andThen(other)

/** compose a [[Fold]] with a [[PTraversal]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeTraversal[B, C, D](other: PTraversal[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def composeTraversal[B, C, D](other: PTraversal[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** compose a [[Fold]] with a [[POptional]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeOptional[B, C, D](other: POptional[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def composeOptional[B, C, D](other: POptional[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** compose a [[Fold]] with a [[PPrism]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composePrism[B, C, D](other: PPrism[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def composePrism[B, C, D](other: PPrism[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** compose a [[Fold]] with a [[PLens]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeLens[B, C, D](other: PLens[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def composeLens[B, C, D](other: PLens[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** compose a [[Fold]] with a [[PIso]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeIso[B, C, D](other: PIso[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def composeIso[B, C, D](other: PIso[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** alias to composeTraversal */
@deprecated("use andThen", since = "3.0.0-M1")
def ^|->>[B, C, D](other: PTraversal[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def ^|->>[B, C, D](other: PTraversal[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** alias to composeOptional */
@deprecated("use andThen", since = "3.0.0-M1")
def ^|-?[B, C, D](other: POptional[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def ^|-?[B, C, D](other: POptional[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** alias to composePrism */
@deprecated("use andThen", since = "3.0.0-M1")
def ^<-?[B, C, D](other: PPrism[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def ^<-?[B, C, D](other: PPrism[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** alias to composeLens */
@deprecated("use andThen", since = "3.0.0-M1")
def ^|->[B, C, D](other: PLens[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def ^|->[B, C, D](other: PLens[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** alias to composeIso */
@deprecated("use andThen", since = "3.0.0-M1")
def ^<->[B, C, D](other: PIso[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def ^<->[B, C, D](other: PIso[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)
}
119 changes: 72 additions & 47 deletions core/shared/src/main/scala/monocle/syntax/AppliedGetter.scala
Original file line number Diff line number Diff line change
@@ -1,75 +1,100 @@
package monocle.syntax

import monocle.function.{At, Each, FilterIndex, Index}
import monocle.{std, Fold, Getter, Optional, PIso, PLens, POptional, PPrism, PTraversal}
import monocle._
import monocle.function.At

final case class AppliedGetter[S, A](s: S, getter: Getter[S, A]) {
def get: A = getter.get(s)
def exist(p: A => Boolean): Boolean = getter.exist(p)(s)
def find(p: A => Boolean): Option[A] = getter.find(p)(s)
trait AppliedGetter[S, A] extends AppliedFold[S, A] {

def each[C](implicit evEach: Each[A, C]): AppliedFold[S, C] =
andThen(evEach.each)
override def optic: Getter[S, A]

/** Select all the elements which satisfies the predicate.
* This combinator can break the fusion property see Optional.filter for more details.
*/
def filter(predicate: A => Boolean): AppliedFold[S, A] =
andThen(Optional.filter(predicate))
def get: A = optic.get(value)

def filterIndex[I, A1](predicate: I => Boolean)(implicit ev: FilterIndex[A, I, A1]): AppliedFold[S, A1] =
andThen(ev.filterIndex(predicate))

def some[A1](implicit ev1: A =:= Option[A1]): AppliedFold[S, A1] =
override def some[A1](implicit ev1: A =:= Option[A1]): AppliedFold[S, A1] =
adapt[Option[A1]].andThen(std.option.some[A1])

def withDefault[A1](defaultValue: A1)(implicit ev1: A =:= Option[A1]): AppliedGetter[S, A1] =
adapt[Option[A1]].andThen(std.option.withDefault(defaultValue))
override private[monocle] def adapt[A1](implicit evA: A =:= A1): AppliedGetter[S, A1] =
evA.substituteCo[AppliedGetter[S, *]](this)

def andThen[B](other: Getter[A, B]): AppliedGetter[S, B] =
AppliedGetter(value, optic.andThen(other))
}

object AppliedGetter {
def apply[S, A](_value: S, _optic: Getter[S, A]): AppliedGetter[S, A] =
new AppliedGetter[S, A] {
val value: S = _value
val optic: Getter[S, A] = _optic
}

implicit def appliedGetterSyntax[S, A](self: AppliedGetter[S, A]): AppliedGetterSyntax[S, A] =
new AppliedGetterSyntax(self)
}

final case class AppliedGetterSyntax[S, A](private val self: AppliedGetter[S, A]) extends AnyVal {

def withDefault[A1](defaultValue: A1)(implicit evOpt: A =:= Option[A1]): AppliedGetter[S, A1] =
self.adapt[Option[A1]].andThen(std.option.withDefault(defaultValue))

def at[I, A1](i: I)(implicit evAt: At[A, i.type, A1]): AppliedGetter[S, A1] =
andThen(evAt.at(i))
self.andThen(evAt.at(i))

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): AppliedFold[S, A1] =
andThen(evIndex.index(i))
/** compose a [[Fold]] with a [[Fold]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeFold[C](other: Fold[A, C]): AppliedFold[S, C] =
self.andThen(other)

private def adapt[A1](implicit evA: A =:= A1): AppliedGetter[S, A1] =
evA.substituteCo[AppliedGetter[S, *]](this)
/** compose a [[Fold]] with a [[Getter]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeGetter[C](other: Getter[A, C]): AppliedGetter[S, C] =
self.andThen(other)

def andThen[B](other: Fold[A, B]): AppliedFold[S, B] =
AppliedFold(s, getter.andThen(other))
def andThen[B](other: Getter[A, B]): AppliedGetter[S, B] =
AppliedGetter(s, getter.andThen(other))
def andThen[B, C, D](other: PTraversal[A, B, C, D]): AppliedFold[S, C] =
AppliedFold(s, getter.andThen(other))
def andThen[B, C, D](other: POptional[A, B, C, D]): AppliedFold[S, C] =
AppliedFold(s, getter.andThen(other))
def andThen[B, C, D](other: PPrism[A, B, C, D]): AppliedFold[S, C] =
AppliedFold(s, getter.andThen(other))
def andThen[B, C, D](other: PLens[A, B, C, D]): AppliedGetter[S, C] =
AppliedGetter(s, getter.andThen(other))
def andThen[B, C, D](other: PIso[A, B, C, D]): AppliedGetter[S, C] =
AppliedGetter(s, getter.andThen(other))
/** compose a [[Fold]] with a [[PTraversal]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeTraversal[B, C, D](other: PTraversal[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** compose a [[Fold]] with a [[POptional]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeFold[B](other: Fold[A, B]): AppliedFold[S, B] = andThen(other)
def composeOptional[B, C, D](other: POptional[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** compose a [[Fold]] with a [[PPrism]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeGetter[B](other: Getter[A, B]): AppliedGetter[S, B] = andThen(other)
def composePrism[B, C, D](other: PPrism[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** compose a [[Fold]] with a [[PLens]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeTraversal[B, C, D](other: PTraversal[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def composeLens[B, C, D](other: PLens[A, B, C, D]): AppliedGetter[S, C] =
self.andThen(other)

/** compose a [[Fold]] with a [[PIso]] */
@deprecated("use andThen", since = "3.0.0-M1")
def composeOptional[B, C, D](other: POptional[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def composeIso[B, C, D](other: PIso[A, B, C, D]): AppliedGetter[S, C] =
self.andThen(other)

/** alias to composeTraversal */
@deprecated("use andThen", since = "3.0.0-M1")
def composePrism[B, C, D](other: PPrism[A, B, C, D]): AppliedFold[S, C] = andThen(other)
def ^|->>[B, C, D](other: PTraversal[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** alias to composeOptional */
@deprecated("use andThen", since = "3.0.0-M1")
def composeLens[B, C, D](other: PLens[A, B, C, D]): AppliedGetter[S, C] = andThen(other)
def ^|-?[B, C, D](other: POptional[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** alias to composePrism */
@deprecated("use andThen", since = "3.0.0-M1")
def composeIso[B, C, D](other: PIso[A, B, C, D]): AppliedGetter[S, C] = andThen(other)
def ^<-?[B, C, D](other: PPrism[A, B, C, D]): AppliedFold[S, C] =
self.andThen(other)

/** alias to composeLens */
@deprecated("use andThen", since = "3.0.0-M1")
def ^|->[B, C, D](other: PLens[A, B, C, D]): AppliedGetter[S, C] = andThen(other)
def ^|->[B, C, D](other: PLens[A, B, C, D]): AppliedGetter[S, C] =
self.andThen(other)

/** alias to composeIso */
@deprecated("use andThen", since = "3.0.0-M1")
def ^<->[B, C, D](other: PIso[A, B, C, D]): AppliedGetter[S, C] = andThen(other)
def ^<->[B, C, D](other: PIso[A, B, C, D]): AppliedGetter[S, C] =
self.andThen(other)
}
Loading

0 comments on commit 002990e

Please sign in to comment.