-
-
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
Fix #2186: make IndexedStateT stack safe #2187
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2187 +/- ##
==========================================
+ Coverage 94.75% 94.78% +0.03%
==========================================
Files 330 332 +2
Lines 5568 5697 +129
Branches 201 214 +13
==========================================
+ Hits 5276 5400 +124
- Misses 292 297 +5
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.
I wonder checking benchmarks. This might not be measurably slower with the technique it is using.
import java.io.Serializable | ||
|
||
/** | ||
* Internal API (Cats) — A type-aligned seq for representing |
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 actually seems like something to move to kernel since it is not higher kinded very useful.
I see it is private, but lots of use cases could exist for an optimized AndThen.
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.
It is not very clear to me what the boundaries of Cats's sub-projects and packages are.
I can move it to cats-kernel if needed, however I only see a bunch of type classes in cats-kernel, whereas I am seeing data types that aren't type classes in cats.data
.
@johnynek I've added benchmark results, compared with current master, see the description. |
Also let me know what you think about |
// Fusing calls up to a certain threshold, using the fusion | ||
// technique implemented for `cats.effect.IO#map` | ||
this match { | ||
case Single(f, index) if index != 127 => |
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.
Nitpick, can we make this 127 (and at line 32) a constant with a sensible name?
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 suggestion. I've updated the code with a documented constant.
|
If we look at the API of AndThen, from a binary compatibility point of view it is just an alias for Function1. I'm not sure how we could even make a change that would break binary compatibility, yet still be an instance of Function1. Even the apply method on the companion just takes a Function1 and returns and AndThen. So as long as we keep the subclasses private and all the support methods private, I think we should make it available. If for no other reason than cats-effect can use it at that point. |
@johnynek this API is basically fixed to Function1. What I was worrying about was that, outside of |
+1 |
fixed scalastyle issues, will merge after build green. |
Close #2186.
This is very similar in spirit with the PR #2185 that fixes
Kleisli
, but this one is forIndexedStateT
and with a different solution.For
IndexedStateT
instead of piggybacking on anF: Monad
for the stack safety of repeated left binds, this time we are introducing anAndThen
implementation.AndThen
was first introduced incats-effect
for describing functions that are stack safe inandThen
andcompose
, the originalcats.effect.IO
implementation being based on it.Introduced as an internal helper (thus not exposed to the public), this is now used to provide stack safety for
IndexedStateT
.Note that an implementation similar to that of PR #2185 is also possible, deferring this responsibility to
F[_]
, except that this version proposed here works for anyF[_]
when it comes to the stack safety of left associative binds.Benchmarks
I've added a benchmark (see StateTBench) that I used to compare the new implementation with
master
. The results are:There is a difference but is imo insignificant.
FAQ
In preparation for the upcoming discussion:
Could this solution be used for Kleisli?
I do not see a solution, because
andThen
swallows the input and you need it a second time for triggering the instance returned by the mapping function:Unless I'm missing something, the answer is no — but it would have been awesome 😞
Is
AndThen
reusable?Yes, we might end up using it for fixing the stack safety of other data types too.
Should we expose
AndThen
?It's a pretty useful data type, maybe. Currently it's
private[cats]
.