-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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 traverseCollect
to TraverseFilter
typeclass
#4277
Add traverseCollect
to TraverseFilter
typeclass
#4277
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR, looking good! As next steps, do you think we can add a law, syntax (and test for the syntax)?
I added syntax and test for it, but I am not sure if we need laws. Looking at |
Oh that's interesting. I think laws are good to have, in case an implementation overrides this method, and at the very least to exercise this code. It's also often good to have some tests with a concrete implementation testing it works as expected. Here's a recent PR that is a great example: |
By laws you mean we want to have a test proving that |
traverseCollect
to TraverseFilter
typeclass
The law should verify that the actual implementation of the method matches the default implementation—you can reuse the same code. You might find the commentary in #4248 (comment) helpful :) let me know if you have questions! |
I added all necessary stuff (I believe so) :) |
laws/src/main/scala/cats/laws/discipline/TraverseFilterTests.scala
Outdated
Show resolved
Hide resolved
laws/src/main/scala/cats/laws/discipline/TraverseFilterTests.scala
Outdated
Show resolved
Hide resolved
thanks for your PR! |
@@ -22,6 +22,7 @@ | |||
package cats | |||
|
|||
import cats.data.State | |||
import cats.implicits.toTraverseOps |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we write this without the ops import? Current practice is try to avoid circular dependencies between syntax and typeclasses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to do manual sequence
for this operation. WDYT?
@@ -69,7 +68,7 @@ trait TraverseFilter[F[_]] extends FunctorFilter[F] { | |||
* res0: List[Option[String]] = List(Some(two), None) | |||
*/ | |||
def traverseCollect[G[_], A, B](fa: F[A])(f: PartialFunction[A, G[B]])(implicit G: Applicative[G]): G[F[B]] = | |||
traverseFilter(fa)(a => f.lift(a).sequence) | |||
traverseFilter(fa)(a => f.lift(a).map(G.map(_)(Option(_))).getOrElse(G.pure(None))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think sequence
was good, we just can't use the syntax :)
traverseFilter(fa)(a => f.lift(a).map(G.map(_)(Option(_))).getOrElse(G.pure(None))) | |
traverseFilter(fa)(a => Traverse[Option].sequence(f.lift(a))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, while we are at it:
val optF = f.lift
traverseFilter(fa)(a => Traverse[Option].sequence(optF(a)))
so we don't reallocate f.lift
on every item a
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@emilhotkowski I think Oscar's suggestion still applies :) it's a good optimization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added!
Co-authored-by: Arman Bilge <armanbilge@gmail.com>
implicit def toTraverseCollectOps[F[_], G[_], A](fa: F[A]): TraverseCollectOps[F, G, A] = | ||
new TraverseCollectOps(fa) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this just be TraverseFilterOps
? We can add more ops in the future; it's not specific to traverseCollect
I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I followed current implementations like new SequenceFilterOps(fgoa)
I don't know what would be the other solution tbh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah the situation for SequenceFilter
is slighly different, since it only works for F[G[Option[A]]]
, not F[A]
implicit def toSequenceFilterOps[F[_], G[_], A](fgoa: F[G[Option[A]]]): SequenceFilterOps[F, G, A] = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you know where I could find examples to follow? I am not sure what I need to change here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, check out any of the syntax implementations :)
https://github.com/typelevel/cats/tree/main/core/src/main/scala/cats/syntax
I'm just proposing that we rename TraverseCollectOps
to TraverseFilterOps
so that it matches the name of the typeclass and not the operation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand your point now. I thought it was a remark about implementation details. Thanks for your work on this PR !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, sorry I wasn't so clear on that. Great, thank you too!
laws/src/main/scala/cats/laws/discipline/TraverseFilterTests.scala
Outdated
Show resolved
Hide resolved
…cala Co-authored-by: Arman Bilge <armanbilge@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for this!
Thank you for contributing to Cats!
This is a kind reminder to run
sbt +prePR
and commit the changed files, if any, before submitting.