Skip to content

Commit

Permalink
Replace apS with RigidSelective typeclass
Browse files Browse the repository at this point in the history
  • Loading branch information
rossabaker committed Dec 16, 2020
1 parent 37594b9 commit b56130d
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 13 deletions.
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/Monad.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import scala.annotation.implicitNotFound
* Must obey the laws defined in cats.laws.MonadLaws.
*/
@implicitNotFound("Could not find an instance of Monad for ${F}")
@typeclass trait Monad[F[_]] extends FlatMap[F] with Selective[F] {
@typeclass trait Monad[F[_]] extends FlatMap[F] with RigidSelective[F] {
override def map[A, B](fa: F[A])(f: A => B): F[B] =
flatMap(fa)(a => pure(f(a)))

Expand Down
59 changes: 59 additions & 0 deletions core/src/main/scala/cats/RigidSelective.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cats

import simulacrum.typeclass
import scala.annotation.implicitNotFound

@implicitNotFound("Could not find an instance of RigidSelective for ${F}")
@typeclass trait RigidSelective[F[_]] extends Selective[F] {
override def ap[A, B](ff: F[A => B])(fa: F[A]): F[B] = {
val left: F[Either[A => B, B]] = map(ff)(Left(_))
val right: F[(A => B) => B] = map(fa)((a: A) => _(a))
select(left)(right)
}
}

object RigidSelective {
/* ======================================================================== */
/* THE FOLLOWING CODE IS MANAGED BY SIMULACRUM; PLEASE DO NOT EDIT!!!! */
/* ======================================================================== */

/**
* Summon an instance of [[RigidSelective]] for `F`.
*/
@inline def apply[F[_]](implicit instance: RigidSelective[F]): RigidSelective[F] = instance

@deprecated("Use cats.syntax object imports", "2.2.0")
object ops {
implicit def toAllRigidSelectiveOps[F[_], A](target: F[A])(implicit tc: RigidSelective[F]): AllOps[F, A] {
type TypeClassType = RigidSelective[F]
} = new AllOps[F, A] {
type TypeClassType = RigidSelective[F]
val self: F[A] = target
val typeClassInstance: TypeClassType = tc
}
}
trait Ops[F[_], A] extends Serializable {
type TypeClassType <: RigidSelective[F]
def self: F[A]
val typeClassInstance: TypeClassType
}
trait AllOps[F[_], A] extends Ops[F, A] with Selective.AllOps[F, A] {
type TypeClassType <: RigidSelective[F]
}
trait ToRigidSelectiveOps extends Serializable {
implicit def toRigidSelectiveOps[F[_], A](target: F[A])(implicit tc: RigidSelective[F]): Ops[F, A] {
type TypeClassType = RigidSelective[F]
} = new Ops[F, A] {
type TypeClassType = RigidSelective[F]
val self: F[A] = target
val typeClassInstance: TypeClassType = tc
}
}
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToRigidSelectiveOps

/* ======================================================================== */
/* END OF SIMULACRUM-MANAGED CODE */
/* ======================================================================== */

}
14 changes: 4 additions & 10 deletions core/src/main/scala/cats/Selective.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ import scala.annotation.implicitNotFound
select(lhs)(fr)
}

def apS[A, B](ff: F[A => B])(fa: F[A]): F[B] = {
val left: F[Either[A => B, B]] = map(ff)(Left(_))
val right: F[(A => B) => B] = map(fa)((a: A) => _(a))
select(left)(right)
}

@noop
def ifS[A](fCond: F[Boolean])(fTrue: => F[A])(fFalse: => F[A]): F[A] = {
val condition: F[Either[Unit, Unit]] = map(fCond)(if (_) EitherUtil.leftUnit else EitherUtil.unit)
Expand Down Expand Up @@ -57,9 +51,10 @@ object Selective {
type TypeClassType <: Selective[F]
def self: F[A]
val typeClassInstance: TypeClassType
def select[B, C](ff: => F[B => C])(implicit ev$1: A <:< Either[B, C]): F[C] = typeClassInstance.select[B, C](self.asInstanceOf[F[Either[B, C]]])(ff)
def branch[B, C, D](fl: => F[B => D])(fr: => F[C => D])(implicit ev$1: A <:< Either[B, C]): F[D] = typeClassInstance.branch[B, C, D](self.asInstanceOf[F[Either[B, C]]])(fl)(fr)
def apS[B, C](fa: F[B])(implicit ev$1: A <:< (B => C)): F[C] = typeClassInstance.apS[B, C](self.asInstanceOf[F[B => C]])(fa)
def select[B, C](ff: => F[B => C])(implicit ev$1: A <:< Either[B, C]): F[C] =
typeClassInstance.select[B, C](self.asInstanceOf[F[Either[B, C]]])(ff)
def branch[B, C, D](fl: => F[B => D])(fr: => F[C => D])(implicit ev$1: A <:< Either[B, C]): F[D] =
typeClassInstance.branch[B, C, D](self.asInstanceOf[F[Either[B, C]]])(fl)(fr)
}
trait AllOps[F[_], A] extends Ops[F, A] with Applicative.AllOps[F, A] {
type TypeClassType <: Selective[F]
Expand All @@ -80,5 +75,4 @@ object Selective {
/* END OF SIMULACRUM-MANAGED CODE */
/* ======================================================================== */


}
6 changes: 5 additions & 1 deletion laws/src/main/scala/cats/laws/RigidSelectiveLaws.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ trait RigidSelectiveLaws[F[_]] extends SelectiveLaws[F] {
implicit override def F: Selective[F]

def selectiveApply[A, B](fa: F[A], ff: F[A => B]): IsEq[F[B]] =
ff.apS(fa) <-> ff.ap(fa)
ff.ap(fa) <-> {
val left: F[Either[A => B, B]] = ff.map(Left(_))
val right: F[(A => B) => B] = fa.map((a: A) => _(a))
left.select(right)
}

private def ope[A] = F.pure(sys.error("ope!"): A)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ trait RigidSelectiveTests[F[_]] extends SelectiveTests[F] {
}

object RigidSelectiveTests {
def apply[F[_]: Selective]: RigidSelectiveTests[F] =
def apply[F[_]: RigidSelective]: RigidSelectiveTests[F] =
new RigidSelectiveTests[F] {
def laws: RigidSelectiveLaws[F] = RigidSelectiveLaws[F]
}
Expand Down

0 comments on commit b56130d

Please sign in to comment.