Proposal: ParallelLike machinery to open implicit summoning
Nobody has claimed this yet.
- Dominant language
- Scala
- Stars
- 5.5k
- Forks
- 1.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 5
Description
Cats Effect has an unfortunate problem with Parallel in that it defines a more primitive typeclass, Spawn, from which Parallel can be derived. The most intuitive user experience is that Spawn implies Parallel, and in fact this is so intuitive that the fact that it isn't true has tripped me up on several occasions.
In Cats Effect 3, we attempt to address this by providing an orphan instance for Parallel[F] given Spawn[F] in the cats.effect.implicits._ scope, but this requires an explicit import. I would rather not require this, but it is not at present possible. Nor can Cats itself provide this materialization in the same fashion that it does for stdlib orphans, since Cats Effect depends on Cats, meaning that doing so would create a cycle.
The answer used here in most cases is inheritance. For example, Spawn also implies Monad, which works nicely because Spawn inherits from Monad, meaning that the subtyping relation materializes the instance any time Monad[F] is summoned. Unfortunately, Parallel does not play nicely within the functor hierarchy in this fashion, since it uses composition rather than subtyping to encode its class implications (e.g. def monad and def applicative), which in turn conflicts with some direct members of various possible subtypes (including Spawn). Additionally, the use of the Aux pattern makes it very difficult to have this form of class implication.
I believe we can solve this within Cats itself though using machinery like the following:
trait ParallelLike[F[_], G[_]] {
protected[cats] def summonCatsParallel: Parallel.Aux[F, G]
}
object Parallel {
// ...
implicit def catsParallelForParallelLike[F[_], G[_]](
implicit F: ParallelLike[F, G])
: Parallel.Aux[F, G] =
F.summonCatsParallel
}
The ParallelLike class is basically a summoner for Parallel. The idea is that Spawn[F] <: ParallelLike[F, G] (where G is the Par newtype for F). The protected[cats] modifier means that the summonCatsParallel member does not appear as part of the downstream public API, but it remains accessible to the only thing that actually needs it: the catsParallelForParallelLike function.
I believe this resolves the orphan problem in this context. Names subject to bike shedding.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the Cats Parallel typeclass and the Spawn relationship described in the issue, then inspect the existing cats.effect.implicits._ materialization. Done means agreeing on and implementing the proposed ParallelLike-based implicit machinery, including its API and naming, so the explicit import requirement is resolved.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- scala
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100