-
-
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/fix Foldable extensions: findM and collectFirstSomeM #2421
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2421 +/- ##
==========================================
+ Coverage 95.2% 95.22% +0.01%
==========================================
Files 351 351
Lines 6366 6371 +5
Branches 280 279 -1
==========================================
+ Hits 6061 6067 +6
+ Misses 305 304 -1
Continue to review full report at Codecov.
|
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.
Great work, thank you :)
def findM[G[_]](p: A => G[Boolean])(implicit F: Foldable[F], G: Monad[G]): G[Option[A]] = | ||
F.foldRight(fa, Eval.now(G.pure(Option.empty[A])))((a, lb) => | ||
Eval.now(G.flatMap(p(a))(if (_) G.pure(Some(a)) else lb.value)) | ||
).value |
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’m worried about stack safety here. Note findM, foldM and existsM use tailRecM to be stack safe.
Can we make Source package private so that we can use it here with tailRecM?
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.
Good point. I assumed stack-safety is provided by safe flatMap implementation. Will rework via tailRecM.
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.
Also added stack-safety tests for other monadic folds.
Fix implementation for findM and collectFirstSomeM extensions for Foldable vai tailRecM, make Foldable.Source package private
Can anything else be improved here to give it the green light? |
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.
This looks good to me, thank you! Excellent 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.
minor comment.
* }}} | ||
*/ | ||
def findM[G[_]](p: A => G[Boolean])(implicit F: Foldable[F], G: Monad[G]): G[Option[A]] = | ||
G.tailRecM(Foldable.Source.fromFoldable(fa))(_.uncons match { |
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.
couldn't this be collectFirstSome { a => p(a).map(if (_) Some(a) else 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.
Sure it could but would require an extra map
for each iteration. I just followed the recommendation of other contributors to prefer efficiency over conciseness in code.
Shall we merge this, then? :) |
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.
👍
@catostrophe Thanks for cleaning up after me |
#2365 seems abandoned, so this is a rework of
findM
implemented as a syntax extension for binary compatibility. Another but equivalent implementation chosen, becauseFoldable.Source
is private.