Add CommutativeApply and CommutativeApplicative - #1927
Conversation
…mmutativeSemigroup, ?]
8c95312 to
0ea4ac0
Compare
Codecov Report
@@ Coverage Diff @@
## master #1927 +/- ##
==========================================
- Coverage 96.21% 96.13% -0.09%
==========================================
Files 272 278 +6
Lines 4628 4655 +27
Branches 124 130 +6
==========================================
+ Hits 4453 4475 +22
- Misses 175 180 +5
Continue to review full report at Codecov.
|
| * | ||
| * Must obey the laws defined in cats.laws.CommutativeApplicativeLaws. | ||
| */ | ||
| @typeclass trait CommutativeApplicative[F[_]] extends Applicative[F] with CommutativeApply[F] |
There was a problem hiding this comment.
For some reason Codecov doesn't think this is being hit, does anyone know why?
|
This seems like a very interesting property (one that Option springs to mind as a canonical example), but chat can I do with an instance? Can we not write a method or two to show the value of the abstraction. I tend to think to make it into cats an abstraction needs to pay its way. I haven’t yet seen that here, but probably because I am unfamiliar. |
|
You could use this property to properly constrain general rewrite systems like monadless (which preserves equational reasoning only for commutative monads). None of these observations leads us closer to an easy example though. @edmundnoble mentioned that it might be handy for optimizing free applicatives since you could re-order effects. |
|
@johnynek Given the ability to reorder computations in FreeApplicative, you can batch them safely. Also, unordered containers can be traversed safely with |
|
those are good examples. Could we add the methods to this PR? |
|
Hmm, so as I see we could either create some sort of Leaning towards the former, as the latter might open another larger can of worms (Would a On another note, once #1837 is merged, I'm pretty sure all the |
ef2c94b to
edd6ba8
Compare
edd6ba8 to
0cd4eb9
Compare
|
Okay, maybe |
This reverts commit 0cd4eb9.
|
@LukaJCB What was the issue with |
|
Yeah, but only if the result is successful: |
|
@LukaJCB hell. Can't ever win with |
|
You really can't 😄. Want to weigh in on syntax sugar vs type class? :) |
6c2a240 to
fcb429d
Compare
|
Another cool thing is that |
fcb429d to
5bf6f35
Compare
5bf6f35 to
d3a803a
Compare
| } | ||
|
|
||
| private[data] sealed abstract class NestedInstances11 extends NestedInstances12 { | ||
| implicit def catsDataCommutativeApplyForNestedContravariant[F[_]: CommutativeApply, G[_]: CommutativeApply]: CommutativeApply[Nested[F, G, ?]] = |
There was a problem hiding this comment.
Usually we place more specific instance higher priority, i.e. CommutativeApply and CommutativeApplicative should have higher priority than Apply and Applicative.
CommutativeApplicative should have higher priority than CommutativeApply.
Also line 53 the instance name was wrong catsDataContravariantForNested -> catsDataFunctorForNested do you mind fix that in this PR as well?
| * | ||
| * Must obey the laws defined in cats.laws.CommutativeApplicativeLaws. | ||
| */ | ||
| @typeclass trait CommutativeApplicative[F[_]] extends Applicative[F] with CommutativeApply[F] { |
There was a problem hiding this comment.
I wonder if we really want an UnorderedFoldable and UnorderedTraverse that instead of toList has toSet and has a foldMap that takes a CommutativeMonoid and for sequence/traverse uses CommutativeApplicative.
That seems cleaner to me than putting these methods here now that I think about it.
I think we can construct sane laws for UnorderedFoldable that would make sense. If we added a method like insert[T](f: F[T], item: T): F[T] then I think you could make some law.
There was a problem hiding this comment.
I agree that an extra type class would feel a lot cleaner than baking these 4 operations into the CommutativeApplicative type class. Related thoughts here.
I've played around with some laws, and we wouldn't have to get rid of too many laws too make it fit. I also like the insert, although I'd have to think about it more. We could let Foldable extend UnorderedFoldable, if that makes any sense. I'll play around with it and update the PR accordingly :)
There was a problem hiding this comment.
This opens up a can of worms though. We could probably also define something like unorderedFoldM with CommutativeMonad, a UnorderedReducible, NonEmptyUnordered and all kinds of others. I came up with something crazy a while ago on gitter https://gitter.im/typelevel/cats-dev?at=59cf81a5210ac269208e0bcf but seems I've only scratched the surface 😄
I'll try to define this as minimal as possible and go from there. Might make a good blog post though.
There was a problem hiding this comment.
I had to remove insert for now, because it's not possible to implement it for Map :/
d3f10ca to
d308cf7
Compare
|
I have a proposal: |
|
Yeah I can do that :) |
4889a52 to
e0069a8
Compare
…l functions there" This reverts commit d308cf7.
908c914 to
305d740
Compare
| checkAll("Map[Int, Int] with Option", TraverseTests[Map[Int, ?]].traverse[Int, Int, Int, Int, Option, Option]) | ||
| checkAll("Traverse[Map[Int, ?]]", SerializableTests.serializable(Traverse[Map[Int, ?]])) | ||
|
|
||
| test("traverseUnordered identity") { |
There was a problem hiding this comment.
you forgot to remove these tests
305d740 to
028b9a7
Compare
This reverts commit 0ffbc55.
028b9a7 to
d673655
Compare
|
Moved the unordered stuff to #1981 |
|
thanks so much! @LukaJCB |
Had a quick discussion about this on gitter. Also adds an instance for
Validated[E: CommutativeSemigroup, ?]:)