Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add shortcuts for at, index #978

Merged
merged 7 commits into from
Dec 6, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion core/shared/src/main/scala/monocle/Fold.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import cats.arrow.Choice
import cats.instances.int._
import cats.instances.list._
import cats.syntax.either._
import monocle.function.Each
import monocle.function.{At, Each, Index}
import monocle.internal.Monoids

/** A [[Fold]] can be seen as a [[Getter]] with many targets or
Expand Down Expand Up @@ -100,6 +100,12 @@ abstract class Fold[S, A] extends Serializable { self =>
private def adapt[A1](implicit evA: A =:= A1): Fold[S, A1] =
evA.substituteCo[Fold[S, *]](this)

def at[I, A1](i: I)(implicit evAt: At[A, i.type, A1]): Fold[S, A1] =
composeLens(evAt.at(i))

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

/** compose a [[Fold]] with another [[Fold]] */
final def andThen[B](other: Fold[A, B]): Fold[S, B] =
new Fold[S, B] {
Expand Down
8 changes: 7 additions & 1 deletion core/shared/src/main/scala/monocle/Getter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package monocle
import cats.{Eq, Monoid, Semigroupal}
import cats.arrow.{Arrow, Choice}
import cats.implicits._
import monocle.function.Each
import monocle.function.{At, Each, Index}

/** A [[Getter]] can be seen as a glorified get method between
* a type S and a type A.
Expand Down Expand Up @@ -65,6 +65,12 @@ abstract class Getter[S, A] extends Serializable { self =>
private def adapt[A1](implicit evA: A =:= A1): Getter[S, A1] =
evA.substituteCo[Getter[S, *]](this)

def at[I, A1](i: I)(implicit evAt: At[A, i.type, A1]): Getter[S, A1] =
composeLens(evAt.at(i))

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

/** compose a [[Getter]] with a [[Fold]] */
final def andThen[B](other: Fold[A, B]): Fold[S, B] =
asFold.andThen(other)
Expand Down
8 changes: 7 additions & 1 deletion core/shared/src/main/scala/monocle/Iso.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import cats.{Applicative, Eq, Functor, Monoid}
import cats.arrow.Category
import cats.evidence.{<~<, Is}
import cats.syntax.either._
import monocle.function.Each
import monocle.function.{At, Each, Index}

/** [[Iso]] is a type alias for [[PIso]] where `S` = `A` and `T` = `B`:
* {{{
Expand Down Expand Up @@ -408,4 +408,10 @@ final case class IsoSyntax[S, A](private val self: Iso[S, A]) extends AnyVal {

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

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): Optional[S, A1] =
self composeOptional evIndex.index(i)
}
8 changes: 7 additions & 1 deletion core/shared/src/main/scala/monocle/Lens.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package monocle
import cats.{Applicative, Eq, Functor, Monoid}
import cats.arrow.Choice
import cats.syntax.either._
import monocle.function.Each
import monocle.function.{At, Each, Index}

/** A [[PLens]] can be seen as a pair of functions:
* - `get: S => A` i.e. from an `S`, we can extract an `A`
Expand Down Expand Up @@ -319,4 +319,10 @@ final case class LensSyntax[S, A](private val self: Lens[S, A]) extends AnyVal {

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

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): Optional[S, A1] =
self composeOptional evIndex.index(i)
}
8 changes: 7 additions & 1 deletion core/shared/src/main/scala/monocle/Optional.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package monocle
import cats.{Applicative, Eq, Monoid}
import cats.arrow.Choice
import cats.syntax.either._
import monocle.function.Each
import monocle.function.{At, Each, Index}

/** A [[POptional]] can be seen as a pair of functions:
* - `getOrModify: S => Either[T, A]`
Expand Down Expand Up @@ -335,4 +335,10 @@ final case class OptionalSyntax[S, A](private val self: Optional[S, A]) extends

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

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): Optional[S, A1] =
self composeOptional evIndex.index(i)
}
8 changes: 7 additions & 1 deletion core/shared/src/main/scala/monocle/Prism.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import cats.arrow.Category
import cats.evidence.{<~<, Is}
import cats.instances.option._
import cats.syntax.either._
import monocle.function.Each
import monocle.function.{At, Each, Index}

/** A [[PPrism]] can be seen as a pair of functions:
* - `getOrModify: S => Either[T, A]`
Expand Down Expand Up @@ -374,4 +374,10 @@ final case class PrismSyntax[S, A](private val self: Prism[S, A]) extends AnyVal

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

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): Optional[S, A1] =
self composeOptional evIndex.index(i)
}
8 changes: 7 additions & 1 deletion core/shared/src/main/scala/monocle/Setter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import cats.{Contravariant, Eq, Functor}
import cats.arrow.Choice
import cats.arrow.Profunctor
import cats.syntax.either._
import monocle.function.Each
import monocle.function.{At, Each, Index}

/** A [[PSetter]] is a generalisation of Functor map:
* - `map: (A => B) => F[A] => F[B]`
Expand Down Expand Up @@ -198,4 +198,10 @@ final case class SetterSyntax[S, A](private val self: Setter[S, A]) extends AnyV

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

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): Setter[S, A1] =
self composeOptional evIndex.index(i)
}
8 changes: 7 additions & 1 deletion core/shared/src/main/scala/monocle/Traversal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import cats.data.Const
import cats.instances.int._
import cats.instances.list._
import cats.syntax.either._
import monocle.function.Each
import monocle.function.{At, Each, Index}
import monocle.internal.Monoids

/** A [[PTraversal]] can be seen as a [[POptional]] generalised to 0 to n targets
Expand Down Expand Up @@ -345,4 +345,10 @@ final case class TraversalSyntax[S, A](private val self: Traversal[S, A]) extend

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

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): Traversal[S, A1] =
self composeOptional evIndex.index(i)
}
29 changes: 21 additions & 8 deletions core/shared/src/main/scala/monocle/syntax/ApplyFold.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package monocle.syntax

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

case class ApplyFold[S, A](s: S, _fold: Fold[S, A]) {
Expand All @@ -17,16 +17,10 @@ case class ApplyFold[S, A](s: S, _fold: Fold[S, A]) {
@inline def isEmpty: Boolean = _fold.isEmpty(s)
@inline def nonEmpty: Boolean = _fold.nonEmpty(s)

def each[C](implicit evEach: Each[A, C]): ApplyFold[S, C] =
composeTraversal(evEach.each)

def some[A1](implicit ev1: A =:= Option[A1]): ApplyFold[S, A1] =
adapt[Option[A1]] composePrism (std.option.pSome)

def withDefault[A1: Eq](defaultValue: A1)(implicit ev1: A =:= Option[A1]): ApplyFold[S, A1] =
adapt[Option[A1]] composeIso (std.option.withDefault(defaultValue))

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

def andThen[B](other: Fold[A, B]): ApplyFold[S, B] =
Expand Down Expand Up @@ -67,3 +61,22 @@ case class ApplyFold[S, A](s: S, _fold: Fold[S, A]) {
/** alias to composeIso */
@inline def ^<->[B, C, D](other: PIso[A, B, C, D]): ApplyFold[S, C] = andThen(other)
}

object ApplyFold {
implicit def applyFoldSyntax[S, A](self: ApplyFold[S, A]): ApplyFoldSyntax[S, A] =
new ApplyFoldSyntax(self)
}

final case class ApplyFoldSyntax[S, A](self: ApplyFold[S, A]) extends AnyVal {
sapizhak marked this conversation as resolved.
Show resolved Hide resolved
def each[C](implicit evEach: Each[A, C]): ApplyFold[S, C] =
self composeTraversal evEach.each

def withDefault[A1: Eq](defaultValue: A1)(implicit ev1: A =:= Option[A1]): ApplyFold[S, A1] =
self.adapt[Option[A1]] composeIso std.option.withDefault(defaultValue)

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): ApplyFold[S, A1] =
self composeOptional evIndex.index(i)
}
29 changes: 21 additions & 8 deletions core/shared/src/main/scala/monocle/syntax/ApplyGetter.scala
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
package monocle.syntax

import cats.Eq
import monocle.function.Each
import monocle.function.{At, Each, Index}
import monocle.{std, Fold, Getter, PIso, PLens, POptional, PPrism, PTraversal}

final case class ApplyGetter[S, A](s: S, getter: Getter[S, A]) {
@inline def get: A = getter.get(s)
@inline def exist(p: A => Boolean): S => Boolean = getter.exist(p)
@inline def find(p: A => Boolean): S => Option[A] = getter.find(p)

def each[C](implicit evEach: Each[A, C]): ApplyFold[S, C] =
composeTraversal(evEach.each)

def some[A1](implicit ev1: A =:= Option[A1]): ApplyFold[S, A1] =
adapt[Option[A1]] composePrism (std.option.pSome)

def withDefault[A1: Eq](defaultValue: A1)(implicit ev1: A =:= Option[A1]): ApplyGetter[S, A1] =
adapt[Option[A1]] composeIso (std.option.withDefault(defaultValue))

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

def andThen[B](other: Fold[A, B]): ApplyFold[S, B] =
Expand Down Expand Up @@ -50,3 +44,22 @@ final case class ApplyGetter[S, A](s: S, getter: Getter[S, A]) {
/** alias to composeIso */
@inline def ^<->[B, C, D](other: PIso[A, B, C, D]): ApplyGetter[S, C] = andThen(other)
}

object ApplyGetter {
implicit def applyGetterSyntax[S, A](self: ApplyGetter[S, A]): ApplyGetterSyntax[S, A] =
new ApplyGetterSyntax(self)
}

final case class ApplyGetterSyntax[S, A](self: ApplyGetter[S, A]) extends AnyVal {
def each[C](implicit evEach: Each[A, C]): ApplyFold[S, C] =
self composeTraversal evEach.each

def withDefault[A1: Eq](defaultValue: A1)(implicit ev1: A =:= Option[A1]): ApplyGetter[S, A1] =
self.adapt[Option[A1]] composeIso std.option.withDefault(defaultValue)

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): ApplyFold[S, A1] =
self composeOptional evIndex.index(i)
}
8 changes: 7 additions & 1 deletion core/shared/src/main/scala/monocle/syntax/ApplyIso.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package monocle.syntax

import cats.{Eq, Functor}
import monocle.function.Each
import monocle.function.{At, Each, Index}
import monocle.{std, Fold, Getter, PIso, PLens, POptional, PPrism, PSetter, PTraversal}

final case class ApplyIso[S, T, A, B](s: S, iso: PIso[S, T, A, B]) {
Expand Down Expand Up @@ -75,4 +75,10 @@ final case class ApplyIsoSyntax[S, A](private val self: ApplyIso[S, S, A, A]) ex

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

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): ApplyOptional[S, S, A1, A1] =
self composeOptional evIndex.index(i)
}
8 changes: 7 additions & 1 deletion core/shared/src/main/scala/monocle/syntax/ApplyLens.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package monocle.syntax

import cats.{Eq, Functor}
import monocle.function.Each
import monocle.function.{At, Each, Index}
import monocle.{std, Fold, Getter, PIso, PLens, POptional, PPrism, PSetter, PTraversal}

final case class ApplyLens[S, T, A, B](s: S, lens: PLens[S, T, A, B]) {
Expand Down Expand Up @@ -76,4 +76,10 @@ final case class ApplyLensSyntax[S, A](private val self: ApplyLens[S, S, A, A])

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

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): ApplyOptional[S, S, A1, A1] =
self composeOptional evIndex.index(i)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package monocle.syntax

import cats.{Applicative, Eq}
import monocle.function.Each
import monocle.function.{At, Each, Index}
import monocle.{std, Fold, PIso, PLens, POptional, PPrism, PSetter, PTraversal}

final case class ApplyOptional[S, T, A, B](s: S, optional: POptional[S, T, A, B]) {
Expand Down Expand Up @@ -83,4 +83,10 @@ final case class ApplyOptionalSyntax[S, A](private val self: ApplyOptional[S, S,

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

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): ApplyOptional[S, S, A1, A1] =
self composeOptional evIndex.index(i)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package monocle.syntax

import cats.{Applicative, Eq}
import monocle.function.Each
import monocle.function.{At, Each, Index}
import monocle.{std, Fold, PIso, PLens, POptional, PPrism, PSetter, PTraversal}

final case class ApplyPrism[S, T, A, B](s: S, prism: PPrism[S, T, A, B]) {
Expand Down Expand Up @@ -81,4 +81,10 @@ final case class ApplyPrismSyntax[S, A](private val self: ApplyPrism[S, S, A, A]

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

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): ApplyOptional[S, S, A1, A1] =
self composeOptional evIndex.index(i)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package monocle.syntax

import cats.Eq
import monocle.function.Each
import monocle.function.{At, Each, Index}
import monocle.{std, PIso, PLens, POptional, PPrism, PSetter, PTraversal}

final case class ApplySetter[S, T, A, B](s: S, setter: PSetter[S, T, A, B]) {
Expand Down Expand Up @@ -66,4 +66,10 @@ final case class ApplySetterSyntax[S, A](private val self: ApplySetter[S, S, A,

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

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): ApplySetter[S, S, A1, A1] =
self composeOptional evIndex.index(i)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package monocle.syntax

import cats.{Applicative, Eq}
import monocle.function.Each
import monocle.function.{At, Each, Index}
import monocle.{std, Fold, PIso, PLens, POptional, PPrism, PSetter, PTraversal}

final case class ApplyTraversal[S, T, A, B](s: S, traversal: PTraversal[S, T, A, B]) {
Expand Down Expand Up @@ -81,4 +81,10 @@ final case class ApplyTraversalSyntax[S, A](private val self: ApplyTraversal[S,

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

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

def index[I, A1](i: I)(implicit evIndex: Index[A, I, A1]): ApplyTraversal[S, S, A1, A1] =
self composeOptional evIndex.index(i)
}
Loading