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 Parallel.apply overload with one type parameter #3031

Merged
merged 1 commit into from
Sep 7, 2019

Conversation

travisbrown
Copy link
Contributor

@travisbrown travisbrown commented Sep 7, 2019

I left this out of #3012 intentionally, since I generally avoid overloading and hate the scala.DummyImplicit hack, which is necessary here, and since I didn't think the need for it would come up that often.

As I've been working more with 2.0.0-RC2 this week, though, I've decided that we really do want this Parallel.apply in 2.0, for a few reasons:

  1. The two-type-parameter apply is pretty useless.
  2. The thing people do when a type class doesn't have a useful apply is go to implicitly, which in this case is pretty unhelpful for something like Parallel[Stream], since its static return type is unrefined. To get a usefully typed instance, you have to go to something like Shapeless's the or define your own version of Parallel.apply with a single parameter.
  3. In practice using Parallel syntax still can be not a great user experience, for a number of reasons, like the fact that if you're working with something like EitherT, you might expect the Parallel[EitherT[F, E, *]] to be in implicit scope, since a lot of EitherT's other instances are (Traverse, Monad, etc.), but no, it has to be imported. When I get frustrated by a type class's syntax, I just fall back to trying to use its apply and call the methods on the instance directly, which at least shrinks the problem space. In this case, where frustration is especially likely, you really want a Parallel.apply that isn't useless.

The implementation is pretty straightforward apart from the horrible scala.DummyImplicit part, but without that we'd need a new method name, and the whole point here is easy discovery and matching users' expectations, so I think overloading is the right approach.

The tests are pretty simple checks that the static types come out right. I've also added tests for the old two-type-parameter overloads for consistency.

Update: note that this change technically breaks source compatibility—it causes the following code not to compile, although it was fine in 2.0.0-RC2:

import cats.Parallel, cats.data.ZipStream, cats.implicits._

Parallel.apply: Parallel.Aux[Stream, ZipStream]

Same with this (it compiles with 2.0.0-RC2, but not after this change):

val p: Parallel.Aux[Stream, ZipStream] = Parallel.apply

Neither of the following compile with 2.0.0-RC1, but off the top of my head I'm not sure why (I only tried 2.13): Both of the following are also fine with 1.x or 2.0.0-RC1 on 2.12 (not 2.0.0-RC1 on 2.13, but that's because of some unrelated aliasing stuff):

Parallel.apply: Parallel[Stream, ZipStream]
val p: Parallel[Stream, ZipStream] = Parallel.apply

There's no reason I can think of that someone would want to do any of this in real code, and I'd be very surprised if it causes problems for anyone.

Copy link
Member

@LukaJCB LukaJCB left a comment

Choose a reason for hiding this comment

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

Good catch 👍

@travisbrown
Copy link
Contributor Author

You don't think we need another RC, do you @LukaJCB? I know overloads can sometimes interact weirdly with type inference, etc., but in this case the whole point is that you're providing the types explicitly, so personally I'm not too worried about it.

@codecov-io
Copy link

codecov-io commented Sep 7, 2019

Codecov Report

Merging #3031 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #3031   +/-   ##
=======================================
  Coverage   93.56%   93.56%           
=======================================
  Files         368      368           
  Lines        6949     6949           
  Branches      195      195           
=======================================
  Hits         6502     6502           
  Misses        447      447
Impacted Files Coverage Δ
core/src/main/scala/cats/Parallel.scala 84.37% <ø> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 802940c...ca3cb72. Read the comment docs.

@travisbrown
Copy link
Contributor Author

For what it's worth I've been playing with this a little more and I think that for any cases where for some reason you want type inference for Parallel.apply, you can just use implicitly instead.

@kailuowang kailuowang merged commit e87c56e into typelevel:master Sep 7, 2019
@travisbrown travisbrown added this to the 2.0.0-RC3 milestone Sep 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants