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

Make whenA/unlessA syntax by-name lazy #4207

Merged
merged 10 commits into from
May 23, 2022
17 changes: 16 additions & 1 deletion core/src/main/scala/cats/syntax/applicative.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,31 @@ package syntax
trait ApplicativeSyntax {
implicit final def catsSyntaxApplicativeId[A](a: A): ApplicativeIdOps[A] =
new ApplicativeIdOps[A](a)
implicit final def catsSyntaxApplicative[F[_], A](fa: F[A]): ApplicativeOps[F, A] =
implicit final def catsSyntaxApplicativeByName[F[_], A](fa: => F[A]): ApplicativeByNameOps[F, A] =
new ApplicativeByNameOps[F, A](() => fa)
implicit final def catsSyntaxApplicativeByValue[F[_], A](fa: F[A]): ApplicativeByValueOps[F, A] =
new ApplicativeByValueOps[F, A](fa)
@deprecated("Use by-value or by-name version", "2.8.0")
final def catsSyntaxApplicative[F[_], A](fa: F[A]): ApplicativeOps[F, A] =
new ApplicativeOps[F, A](fa)
}

final class ApplicativeIdOps[A](private val a: A) extends AnyVal {
def pure[F[_]](implicit F: Applicative[F]): F[A] = F.pure(a)
}

@deprecated("Use by-value or by-name version", "2.8.0")
final class ApplicativeOps[F[_], A](private val fa: F[A]) extends AnyVal {
def replicateA(n: Int)(implicit F: Applicative[F]): F[List[A]] = F.replicateA(n, fa)
def unlessA(cond: Boolean)(implicit F: Applicative[F]): F[Unit] = F.unlessA(cond)(fa)
def whenA(cond: Boolean)(implicit F: Applicative[F]): F[Unit] = F.whenA(cond)(fa)
}

final class ApplicativeByValueOps[F[_], A](private val fa: F[A]) extends AnyVal {
def replicateA(n: Int)(implicit F: Applicative[F]): F[List[A]] = F.replicateA(n, fa)
}

final class ApplicativeByNameOps[F[_], A](private val fa: () => F[A]) extends AnyVal {
def unlessA(cond: Boolean)(implicit F: Applicative[F]): F[Unit] = F.unlessA(cond)(fa())
def whenA(cond: Boolean)(implicit F: Applicative[F]): F[Unit] = F.whenA(cond)(fa())
}
10 changes: 10 additions & 0 deletions tests/shared/src/test/scala/cats/tests/ApplicativeSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ class ApplicativeSuite extends CatsSuite {
}
}

test("by-name ops are lazy") {
var i = 0
Option(i += 1).whenA(false)
assertEquals(i, 0)

var j = 0
Option(j += 1).unlessA(true)
assertEquals(j, 0)
}

{
implicit val optionMonoid: Monoid[Option[Int]] = Applicative.monoid[Option, Int]
checkAll("Applicative[Option].monoid", MonoidTests[Option[Int]](optionMonoid).monoid)
Expand Down