package monocle
import scalaz.{Choice, Functor, \/}
abstract class PSetter[S, T, A, B] extends Serializable { self =>
def modify(f: A => B): S => T
def set(b: B): S => T
@inline final def sum[S1, T1](other: PSetter[S1, T1, A, B]): PSetter[S \/ S1, T \/ T1, A, B] =
PSetter[S \/ S1, T \/ T1, A, B](
b => _.bimap(self.modify(b), other.modify(b))
)
@inline final def composeSetter[C, D](other: PSetter[A, B, C, D]): PSetter[S, T, C, D] =
new PSetter[S, T, C, D]{
def modify(f: C => D): S => T =
self.modify(other.modify(f))
def set(d: D): S => T =
self.modify(other.set(d))
}
@inline final def composeTraversal[C, D](other: PTraversal[A, B, C, D]): PSetter[S, T, C, D] =
composeSetter(other.asSetter)
@inline final def composeOptional[C, D](other: POptional[A, B, C, D]): PSetter[S, T, C, D] =
composeSetter(other.asSetter)
@inline final def composePrism[C, D](other: PPrism[A, B, C, D]): PSetter[S, T, C, D] =
composeSetter(other.asSetter)
@inline final def composeLens[C, D](other: PLens[A, B, C, D]): PSetter[S, T, C, D] =
composeSetter(other.asSetter)
@inline final def composeIso[C, D](other: PIso[A, B, C, D]): PSetter[S, T, C, D] =
composeSetter(other.asSetter)
@inline final def ^|->>[C, D](other: PTraversal[A, B, C, D]): PSetter[S, T, C, D] =
composeTraversal(other)
@inline final def ^|-?[C, D](other: POptional[A, B, C, D]): PSetter[S, T, C, D] =
composeOptional(other)
@inline final def ^<-?[C, D](other: PPrism[A, B, C, D]): PSetter[S, T, C, D] =
composePrism(other)
@inline final def ^|->[C, D](other: PLens[A, B, C, D]): PSetter[S, T, C, D] =
composeLens(other)
@inline final def ^<->[C, D](other: PIso[A, B, C, D]): PSetter[S, T, C, D] =
composeIso(other)
}
object PSetter extends SetterInstances {
def id[S, T]: PSetter[S, T, S, T] =
PIso.id[S, T].asSetter
def codiagonal[S, T]: PSetter[S \/ S, T \/ T, S, T] =
PSetter[S \/ S, T \/ T, S, T](f => _.bimap(f,f))
def apply[S, T, A, B](_modify: (A => B) => S => T): PSetter[S, T, A, B] =
new PSetter[S, T, A, B]{
def modify(f: A => B): S => T =
_modify(f)
def set(b: B): S => T =
_modify(_ => b)
}
def fromFunctor[F[_]: Functor, A, B]: PSetter[F[A], F[B], A, B] =
PSetter[F[A], F[B], A, B](f => Functor[F].map(_)(f))
}
object Setter {
def id[A]: Setter[A, A] =
Iso.id[A].asSetter
def codiagonal[S]: Setter[S \/ S, S] =
PSetter.codiagonal
def apply[S, A](modify: (A => A) => S => S): Setter[S, A] =
PSetter(modify)
}
sealed abstract class SetterInstances {
implicit val SetterChoice: Choice[Setter] = new Choice[Setter] {
def compose[A, B, C](f: Setter[B, C], g: Setter[A, B]): Setter[A, C] =
g composeSetter f
def id[A]: Setter[A, A] =
Setter.id
def choice[A, B, C](f1: => Setter[A, C], f2: => Setter[B, C]): Setter[A \/ B, C] =
f1 sum f2
}
}