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

Parallel for EitherT and IorT is probably over constrained #3776

Closed
djspiewak opened this issue Feb 7, 2021 · 4 comments · Fixed by #3777
Closed

Parallel for EitherT and IorT is probably over constrained #3776

djspiewak opened this issue Feb 7, 2021 · 4 comments · Fixed by #3777
Milestone

Comments

@djspiewak
Copy link
Member

For more discussion on this, see typelevel/cats-effect#1645. The short form is that EitherT and IorT require a Semigroup/Monoid on their error type to derive a Parallel. This gives rise to semantics which are inconsistent with more fundamental derivations of the Parallel type.

At the present moment, it is undecided how best to resolve this, but one possibility is to change the derivations in Cats itself, which is what this issue is now tracking.

@djspiewak djspiewak added this to the 2.4 milestone Feb 7, 2021
@LukaJCB
Copy link
Member

LukaJCB commented Feb 8, 2021

Urgh this is totally my bad. It's because the semantics are taken from Either, which through Parallel turns into Validated and therefore requires the monoid constraint. Seemed like a good idea at the time...

@Baccata
Copy link
Contributor

Baccata commented Feb 8, 2021

inconsistent with more fundamental derivations of the Parallel type.

@djspiewak, how are the derivations you're thinking of more fundamental ? The layering of semantics via a monad stack is interesting because the composition of layers respects the semantics of each layer individually. I'd even go as far as saying that this quality should be a fundamental law to the very concept of monad transformer :

  • given M a Monad and MT[*[_], *] its transformer counterpart, M <-> MT[Id, *]

Urgh this is totally my bad. It's because the semantics are taken from Either, which through Parallel turns into Validated and therefore requires the monoid constraint. Seemed like a good idea at the time...

@LukaJCB, I totally agree with these semantics, as a matter of fact, I'm currently facing an actual use-case where EitherT[Writer[L, *], NonEmptyList[E], *] is a perfect fit, because the EitherT's Parallel reflects the behaviour of Either's Parallel, and I can use it that to aggregate errors via a parallel composition.

Changing the behaviour of Parallel for EitherT would completely break this very valid use of it, and I'd be left having to create my own Either, which would utterly suck for a great number of reasons .

@Baccata
Copy link
Contributor

Baccata commented Feb 8, 2021

I think there are three cases to account for :

F[_] \ E Semigroupal Non-semigroupal
Parallel 1.1 EitherT's parallel respects F's parallelism and allows for combining errors 1.2 EitherT's parallel respects F's parallelism but never combines errors
NonParallel 2.1 EitherT's parallel allows for combining errors but always composes F sequentially 2.2 no instance
  • Currently, cats-core has instances for 1.1 and 2.1
  • 1.2 is missing and that's a problem that I think @djspiewak is pointing out
  • Daniel's changes are removing 1.1 in favour of 1.2
  • I think 1.1, 1.2 and 2.1 are all valid cases for Parallel instances on EitherT (and IorT obviously), and that 1.1 should retain highest priority during resolution.

@Baccata
Copy link
Contributor

Baccata commented Feb 8, 2021

Alright so after a chat with @djspiewak, here's my current state of thoughts (echoing #3777 (comment)):

  1. there is no intuition about these things that is inherently correct because the concept of MonadTransformer doesn't come with Laws, and that Parallel itself (despite being a lawful construct) is rather ad-hoc : its meaning is not as well outlined as other typeclasses.
  2. therefore I think that neither Daniel's point of view nor mine are inherently correct on this issue.
  3. in the grand scheme of things, a lot of people have an intuition that Concurrent and Parallel are one and the same thing, which tends to trip up a lot of people. Even if that equivalence is clearly wrong, having Parallel implied easily by Concurrent is very desirable in the ecosystem.
  4. I will not admit that my own intuition about the current Parallel instance for EitherT is invalid, but I'll admit that it makes it harder for point 3 to be delivered.

Therefore I'd be satisfied if there was a way to regain the current semantics. I think I'd favour a non-orphaned instance on a new datatype (or newtype), but if there was an orphan instance that could be accessed easily without colliding with the Concurrent => Parallel one, I'd personally be okay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants