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 doctest examples for Apply #2086

Merged
merged 2 commits into from
Dec 19, 2017
Merged
Changes from all 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
122 changes: 120 additions & 2 deletions core/src/main/scala/cats/Apply.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,97 @@ trait Apply[F[_]] extends Functor[F] with Semigroupal[F] with ApplyArityFunction
/**
* Given a value and a function in the Apply context, applies the
* function to the value.
*
* Example:
* {{{
* scala> import cats.implicits._
*
* scala> val someF: Option[Int => Long] = Some(_.toLong + 1L)
* scala> val noneF: Option[Int => Long] = None
* scala> val someInt: Option[Int] = Some(3)
* scala> val noneInt: Option[Int] = None
*
* scala> Apply[Option].ap(someF)(someInt)
* res0: Option[Long] = Some(4)
*
* scala> Apply[Option].ap(noneF)(someInt)
* res1: Option[Long] = None
*
* scala> Apply[Option].ap(someF)(noneInt)
* res2: Option[Long] = None
*
* scala> Apply[Option].ap(noneF)(noneInt)
* res3: Option[Long] = None
* }}}
*/
def ap[A, B](ff: F[A => B])(fa: F[A]): F[B]

/** Compose two actions, discarding any value produced by the first. */
/**
* Compose two actions, discarding any value produced by the first.
*
* @see [[productL]] to discard the value of the second instead.
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> import cats.data.Validated
* scala> import Validated.{Valid, Invalid}
*
* scala> type ErrOr[A] = Validated[String, A]
*
* scala> val validInt: ErrOr[Int] = Valid(3)
* scala> val validBool: ErrOr[Boolean] = Valid(true)
* scala> val invalidInt: ErrOr[Int] = Invalid("Invalid int.")
* scala> val invalidBool: ErrOr[Boolean] = Invalid("Invalid boolean.")
*
* scala> Apply[ErrOr].productR(validInt)(validBool)
* res0: ErrOr[Boolean] = Valid(true)
*
* scala> Apply[ErrOr].productR(invalidInt)(validBool)
* res1: ErrOr[Boolean] = Invalid(Invalid int.)
*
* scala> Apply[ErrOr].productR(validInt)(invalidBool)
* res2: ErrOr[Boolean] = Invalid(Invalid boolean.)
*
* scala> Apply[ErrOr].productR(invalidInt)(invalidBool)
* res3: ErrOr[Boolean] = Invalid(Invalid int.Invalid boolean.)
* }}}
*
*/
def productR[A, B](fa: F[A])(fb: F[B]): F[B] =
map2(fa, fb)((_, b) => b)

/** Compose two actions, discarding any value produced by the second. */
/**
* Compose two actions, discarding any value produced by the second.
*
* @see [[productR]] to discard the value of the first instead.
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> import cats.data.Validated
* scala> import Validated.{Valid, Invalid}
*
* scala> type ErrOr[A] = Validated[String, A]
*
* scala> val validInt: ErrOr[Int] = Valid(3)
* scala> val validBool: ErrOr[Boolean] = Valid(true)
* scala> val invalidInt: ErrOr[Int] = Invalid("Invalid int.")
* scala> val invalidBool: ErrOr[Boolean] = Invalid("Invalid boolean.")
*
* scala> Apply[ErrOr].productL(validInt)(validBool)
* res0: ErrOr[Int] = Valid(3)
*
* scala> Apply[ErrOr].productL(invalidInt)(validBool)
* res1: ErrOr[Int] = Invalid(Invalid int.)
*
* scala> Apply[ErrOr].productL(validInt)(invalidBool)
* res2: ErrOr[Int] = Invalid(Invalid boolean.)
*
* scala> Apply[ErrOr].productL(invalidInt)(invalidBool)
* res3: ErrOr[Int] = Invalid(Invalid int.Invalid boolean.)
* }}}
*/
def productL[A, B](fa: F[A])(fb: F[B]): F[A] =
map2(fa, fb)((a, _) => a)

Expand Down Expand Up @@ -60,6 +143,28 @@ trait Apply[F[_]] extends Functor[F] with Semigroupal[F] with ApplyArityFunction
* Applies the pure (binary) function f to the effectful values fa and fb.
*
* map2 can be seen as a binary version of [[cats.Functor]]#map.
*
* Example:
* {{{
* scala> import cats.implicits._
*
* scala> val someInt: Option[Int] = Some(3)
* scala> val noneInt: Option[Int] = None
* scala> val someLong: Option[Long] = Some(4L)
* scala> val noneLong: Option[Long] = None
*
* scala> Apply[Option].map2(someInt, someLong)((i, l) => i.toString + l.toString)
* res0: Option[String] = Some(34)
*
* scala> Apply[Option].map2(someInt, noneLong)((i, l) => i.toString + l.toString)
* res0: Option[String] = None
*
* scala> Apply[Option].map2(noneInt, noneLong)((i, l) => i.toString + l.toString)
* res0: Option[String] = None
*
* scala> Apply[Option].map2(noneInt, someLong)((i, l) => i.toString + l.toString)
* res0: Option[String] = None
* }}}
*/
def map2[A, B, Z](fa: F[A], fb: F[B])(f: (A, B) => Z): F[Z] =
map(product(fa, fb))(f.tupled)
Expand Down Expand Up @@ -89,6 +194,19 @@ trait Apply[F[_]] extends Functor[F] with Semigroupal[F] with ApplyArityFunction
def map2Eval[A, B, Z](fa: F[A], fb: Eval[F[B]])(f: (A, B) => Z): Eval[F[Z]] =
fb.map(fb => map2(fa, fb)(f))

/**
* Compose an `Apply[F]` and an `Apply[G]` into an `Apply[λ[α => F[G[α]]]]`.
*
* Example:
* {{{
* scala> import cats.implicits._
*
* scala> val alo = Apply[List].compose[Option]
*
* scala> alo.product(List(None, Some(true), Some(false)), List(Some(2), None))
* res1: List[Option[(Boolean, Int)]] = List(None, None, Some((true,2)), None, Some((false,2)), None)
* }}}
*/
def compose[G[_]: Apply]: Apply[λ[α => F[G[α]]]] =
new ComposedApply[F, G] {
val F = self
Expand Down