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

Change forEffect/followedBy to productL/productR #2083

Merged
merged 18 commits into from
Dec 15, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
28 changes: 15 additions & 13 deletions core/src/main/scala/cats/Apply.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package cats

import simulacrum.typeclass
import simulacrum.{typeclass, noop}

/**
* Weaker version of Applicative[F]; has apply but not pure.
Expand All @@ -16,24 +16,26 @@ trait Apply[F[_]] extends Functor[F] with Semigroupal[F] with ApplyArityFunction
*/
def ap[A, B](ff: F[A => B])(fa: F[A]): F[B]

override def product[A, B](fa: F[A], fb: F[B]): F[(A, B)] =
ap(map(fa)(a => (b: B) => (a, b)))(fb)

/** Compose two actions, discarding any value produced by the first. */
def followedBy[A, B](fa: F[A])(fb: F[B]): F[B] =
def apR[A, B](fa: F[A])(fb: F[B]): F[B] =
map2(fa, fb)((_, b) => b)

/** Alias for [[followedBy]]. */
@inline final def *>[A, B](fa: F[A])(fb: F[B]): F[B] =
followedBy(fa)(fb)

/** Compose two actions, discarding any value produced by the second. */
def forEffect[A, B](fa: F[A])(fb: F[B]): F[A] =
def apL[A, B](fa: F[A])(fb: F[B]): F[A] =
map2(fa, fb)((a, _) => a)

/** Alias for [[forEffect]]. */
@inline final def <*[A, B](fa: F[A])(fb: F[B]): F[A] =
forEffect(fa)(fb)
override def product[A, B](fa: F[A], fb: F[B]): F[(A, B)] =
ap(map(fa)(a => (b: B) => (a, b)))(fb)

/** Alias for [[apR]]. */
@deprecated("Use *> or apR instead.", "1.0.0-RC2")
@noop @inline final def followedBy[A, B](fa: F[A])(fb: F[B]): F[B] =
apR(fa)(fb)

/** Alias for [[apL]]. */
@deprecated("Use <* or apL instead.", "1.0.0-RC2")
@noop @inline final def forEffect[A, B](fa: F[A])(fb: F[B]): F[A] =
apL(fa)(fb)

/**
* ap2 is a binary version of ap, defined in terms of ap.
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/FlatMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import simulacrum.typeclass

/**
* Sequentially compose two actions, discarding any value produced by the first. This variant of
* [[followedBy]] also lets you define the evaluation strategy of the second action. For instance
* [[apR]] also lets you define the evaluation strategy of the second action. For instance
* you can evaluate it only ''after'' the first action has finished:
*
* {{{
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/scala/cats/instances/tuple.scala
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ private[instances] class FlatMapTuple2[X](s: Semigroup[X]) extends FlatMap[(X, ?
(x, xb._2)
}

override def followedBy[A, B](a: (X, A))(b: (X, B)): (X, B) =
override def apR[A, B](a: (X, A))(b: (X, B)): (X, B) =
(s.combine(a._1, b._1), b._2)

override def forEffect[A, B](a: (X, A))(b: (X, B)): (X, A) =
override def apL[A, B](a: (X, A))(b: (X, B)): (X, A) =
(s.combine(a._1, b._1), a._2)

override def mproduct[A, B](fa: (X, A))(f: A => (X, B)): (X, (A, B)) = {
Expand Down
32 changes: 32 additions & 0 deletions core/src/main/scala/cats/syntax/apply.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,36 @@ trait ApplySyntax extends TupleSemigroupalSyntax {
val self = fa
val typeClassInstance = F
}

implicit final def catsSyntaxApplyOps[F[_], A](fa: F[A]): ApplyOps[F, A] =
new ApplyOps(fa)

implicit final def catsSyntaxApplyApOps[F[_], A, B](ff: F[A => B]): ApplyApOps[F, A, B] =
new ApplyApOps(ff)
}

final class ApplyOps[F[_], A](val fa: F[A]) extends AnyVal {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, why is it that this new syntax is needed? Does simulacrum not generate syntax for deprecated methods?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generate as deprecated?

Copy link
Contributor Author

@Jacoby6000 Jacoby6000 Dec 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simulacrum does generate the deprecated methods, which makes scalac complain since it references the original deprecated method.

/** Alias for [[*>]]. */
@deprecated("Use *> or apR instead.", "1.0.0-RC2")
@inline def followedBy[B](fb: F[B])(implicit F: Apply[F]): F[B] =
F.apR(fa)(fb)

/** Alias for [[<*]]. */
@deprecated("Use <* or apL instead.", "1.0.0-RC2")
@inline def forEffect[B](fb: F[B])(implicit F: Apply[F]): F[A] =
F.apL(fa)(fb)

/** Alias for [[Applicative.apR]]. */
@inline def *>[B](fb: F[B])(implicit F: Apply[F]): F[B] =
F.apR(fa)(fb)

/** Alias for [[Applicative.apL]]. */
@inline def <*[B](fb: F[B])(implicit F: Apply[F]): F[A] =
F.apL(fa)(fb)
}

final class ApplyApOps[F[_], A, B](val ff: F[A => B]) extends AnyVal {
/** Alias for [[Applicative.ap]]. */
@inline def <*>(fa: F[A])(implicit F: Apply[F]): F[B] =
F.ap(ff)(fa)
}
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/flatMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ final class FlatMapOps[F[_], A](val fa: F[A]) extends AnyVal {
def >>[B](fb: => F[B])(implicit F: FlatMap[F]): F[B] = F.flatMap(fa)(_ => fb)

@deprecated("Use <* instead", "1.0.0-RC1")
def <<[B](fb: F[B])(implicit F: FlatMap[F]): F[A] = F.forEffect(fa)(fb)
def <<[B](fb: F[B])(implicit F: FlatMap[F]): F[A] = F.apL(fa)(fb)
}

final class FlattenOps[F[_], A](val ffa: F[F[A]]) extends AnyVal {
Expand Down
6 changes: 3 additions & 3 deletions laws/src/main/scala/cats/laws/ApplyLaws.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ trait ApplyLaws[F[_]] extends FunctorLaws[F] with SemigroupalLaws[F] {
F.map(F.product(fa, fb)) { case (a, b) => f(a, b) } <-> F.map2(fa, fb)(f)

def map2EvalConsistency[A, B, C](fa: F[A], fb: F[B], f: (A, B) => C): IsEq[F[C]] =
F.map2(fa, fb)(f) <-> (F.map2Eval(fa, Eval.now(fb))(f).value)
F.map2(fa, fb)(f) <-> F.map2Eval(fa, Eval.now(fb))(f).value

def followedByConsistency[A, B](fa: F[A], fb: F[B]): IsEq[F[B]] =
F.followedBy(fa)(fb) <-> F.map2(fa, fb)((_, b) => b)
F.apR(fa)(fb) <-> F.map2(fa, fb)((_, b) => b)

def forEffectConsistency[A, B](fa: F[A], fb: F[B]): IsEq[F[A]] =
F.forEffect(fa)(fb) <-> F.map2(fa, fb)((a, _) => a)
F.apL(fa)(fb) <-> F.map2(fa, fb)((a, _) => a)
}

object ApplyLaws {
Expand Down