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

Recommend Cats Effect IO as a replacement for every use case of Future #4230

Merged
merged 2 commits into from
Jun 16, 2022
Merged
Show file tree
Hide file tree
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
11 changes: 11 additions & 0 deletions core/src/main/scala-2.12/cats/instances/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,18 @@ package object instances {
object deadline extends DeadlineInstances
object function extends FunctionInstances with FunctionInstancesBinCompat0
object partialFunction extends PartialFunctionInstances

/**
* @deprecated
* Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
* (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
* We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
* However, at this time there are no plans to remove these instances from Cats.
*
* @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
*/
object future extends FutureInstances

object int extends IntInstances
object invariant extends InvariantMonoidalInstances with InvariantInstances with InvariantInstancesBinCompat0
object list extends ListInstances with ListInstancesBinCompat0
Expand Down
11 changes: 11 additions & 0 deletions core/src/main/scala-2.13+/cats/instances/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,18 @@ package object instances {
object deadline extends DeadlineInstances
object function extends FunctionInstances with FunctionInstancesBinCompat0
object partialFunction extends PartialFunctionInstances

/**
* @deprecated
* Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
* (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
* We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
* However, at this time there are no plans to remove these instances from Cats.
*
* @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
*/
object future extends FutureInstances

object int extends IntInstances
object invariant extends InvariantMonoidalInstances with InvariantInstances with InvariantInstancesBinCompat0
object list extends ListInstances with ListInstancesBinCompat0
Expand Down
10 changes: 10 additions & 0 deletions core/src/main/scala/cats/Invariant.scala
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,16 @@ object Invariant extends ScalaVersionSpecificInvariantInstances with InvariantIn

implicit def catsInstancesForTry: MonadThrow[Try] with CoflatMap[Try] =
cats.instances.try_.catsStdInstancesForTry

/**
* @deprecated
* Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
* (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
* We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
* However, at this time there are no plans to remove these instances from Cats.
*
* @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
*/
implicit def catsInstancesForFuture(implicit
ec: ExecutionContext
): MonadThrow[Future] with CoflatMap[Future] =
Expand Down
11 changes: 11 additions & 0 deletions core/src/main/scala/cats/Semigroupal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,19 @@ object Semigroupal extends ScalaVersionSpecificSemigroupalInstances with Semigro
implicit def catsSemigroupalForId: Semigroupal[Id] = catsInstancesForId
implicit def catsSemigroupalForOption: Semigroupal[Option] = cats.instances.option.catsStdInstancesForOption
implicit def catsSemigroupalForTry: Semigroupal[Try] = cats.instances.try_.catsStdInstancesForTry

/**
* @deprecated
* Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
* (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
* We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
Copy link
Member

Choose a reason for hiding this comment

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

I endorse the advertisement of CE, but Monix is good too, maybe it's also worth mentioning?

Copy link
Member Author

Choose a reason for hiding this comment

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

Great point, sure! @danicheg what is the specific, referentially-transparent datatype we should recommend here, would it be Task? Is there any concern to recommend Monix before it has adopted CE3 since it cannot interop with maintained versions of the major libraries?

Copy link
Member Author

Choose a reason for hiding this comment

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

To be fair, anyone who would have used Future would also have run into some interop problems 😂

Copy link
Member

Choose a reason for hiding this comment

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

I think we could advise using some abstract IO datatype and refer to CE and Monix (to libraries, not their concrete datatypes). WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think the kind of user who might be unintentionally using Future with Cats doesn't necessarily have the experience to appreciate what an "abstract IO datatype" is.

For the record, I have essentially no experience with Monix, but it seems to me there are an overwhelming number of datatypes in there, not all of which are RT. So I think it would be helpful to be more a little more specific.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think a clear and direct recommendation for IO is best here. A user who is using Future in a way that's not aware of the RT implications isn't ready for writing tagless style code, so that's out. Monix isn't updated to CE3 and might not be a long time, so that's out (at least for now).

So, IO

* However, at this time there are no plans to remove these instances from Cats.
*
* @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
*/
implicit def catsSemigroupalForFuture(implicit ec: ExecutionContext): Semigroupal[Future] =
cats.instances.future.catsStdInstancesForFuture(ec)

implicit def catsSemigroupalForList: Semigroupal[List] = cats.instances.list.catsStdInstancesForList
implicit def catsSemigroupalForSeq: Semigroupal[Seq] = cats.instances.seq.catsStdInstancesForSeq
implicit def catsSemigroupalForVector: Semigroupal[Vector] = cats.instances.vector.catsStdInstancesForVector
Expand Down
9 changes: 9 additions & 0 deletions core/src/main/scala/cats/instances/future.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ package instances
import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success}

/**
* @deprecated
* Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
* (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
* We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
* However, at this time there are no plans to remove these instances from Cats.
*
* @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
*/
trait FutureInstances extends FutureInstances1 {

implicit def catsStdInstancesForFuture(implicit
Expand Down
20 changes: 20 additions & 0 deletions kernel/src/main/scala/cats/kernel/Semigroup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,19 @@ private[kernel] trait MonoidInstances extends BandInstances {
cats.kernel.instances.either.catsDataMonoidForEither[A, B]
implicit def catsKernelMonoidForTry[A: Monoid]: Monoid[Try[A]] =
new TryMonoid[A](Monoid[A])

/**
* @deprecated
* Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
* (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
* We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
* However, at this time there are no plans to remove these instances from Cats.
*
* @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
*/
implicit def catsKernelMonoidForFuture[A](implicit A: Monoid[A], ec: ExecutionContext): Monoid[Future[A]] =
new FutureMonoid[A](A, ec)

implicit def catsKernelMonoidForOption[A: Semigroup]: Monoid[Option[A]] =
cats.kernel.instances.option.catsKernelStdMonoidForOption[A]
implicit def catsKernelMonoidForSeq[A]: Monoid[Seq[A]] =
Expand Down Expand Up @@ -319,6 +330,15 @@ private[kernel] trait SemigroupInstances {
cats.kernel.instances.either.catsDataSemigroupForEither[A, B]
implicit def catsKernelSemigroupForTry[A: Semigroup]: Semigroup[Try[A]] =
new TrySemigroup[A](Semigroup[A])

/**
* @deprecated
* Any non-pure use of [[scala.concurrent.Future Future]] with Cats is error prone
* (particularly the semantics of [[cats.Traverse#traverse traverse]] with regard to execution order are unspecified).
* We recommend using [[https://typelevel.org/cats-effect/ Cats Effect `IO`]] as a replacement for ''every'' use case of [[scala.concurrent.Future Future]].
*
* @see [[https://github.com/typelevel/cats/issues/4176 Changes in Future traverse behavior between 2.6 and 2.7]]
*/
implicit def catsKernelSemigroupForFuture[A](implicit A: Semigroup[A], ec: ExecutionContext): Semigroup[Future[A]] =
new FutureSemigroup[A](A, ec)
}
Expand Down