Conversation
Codecov Report
@@ Coverage Diff @@
## master #1748 +/- ##
==========================================
+ Coverage 94.81% 94.87% +0.05%
==========================================
Files 241 241
Lines 4092 4139 +47
Branches 95 103 +8
==========================================
+ Hits 3880 3927 +47
Misses 212 212
Continue to review full report at Codecov.
|
5e6adae to
10c6516
Compare
10c6516 to
94159b9
Compare
| ### The way FreeApplicative#foldMap works | ||
| Despite being an imperative loop, there is a functional intuition behind `FreeApplicative#foldMap`. | ||
|
|
||
| The new `FreeAp`'s `foldMap` is a sort of mutually-recursive function that operates on an argument stack and a |
There was a problem hiding this comment.
quick nitpick question: shall we use FreeAp or FreeApplicative in the documentation?
There was a problem hiding this comment.
Good point, I'll try to use FreeApplicative. My bad.
There was a problem hiding this comment.
looks like you forgot about this one?
74554b5 to
bcf954d
Compare
| */ | ||
| final def fold(implicit F: Applicative[F]): F[A] = | ||
| * Tail recursive only if `F` provides tail recursive interpretation. | ||
| */ |
There was a problem hiding this comment.
another nitpick here, the scala doc indentation is changed away from our standard.
There was a problem hiding this comment.
I don't think I know what tail recursive implementation means for Applicative. Can we be more concrete or link somewhere in this comment?
There was a problem hiding this comment.
It's stack-safe. Edit: I see what you mean now. I'll remove this comment, it doesn't make sense to me :P
| */ | ||
| final def fold(implicit F: Applicative[F]): F[A] = { | ||
| foldMap(FunctionK.id[F]) | ||
| } |
There was a problem hiding this comment.
yet another superficial comment, what about all these addition of {. If we want to change the formating rule, shall we use another separate PR?
There was a problem hiding this comment.
IntelliJ is conspiring against me 😛
| r1.foldMap(nt) should === (r2.foldMap(nt)) | ||
| } | ||
|
|
||
| test("FreeApplicative#flatCompile") { |
There was a problem hiding this comment.
How about making this test a scalacheck? In fact, to gain more confidence against the new implementation, how about we convert the existing related tests to scalacheck tests?
There was a problem hiding this comment.
I'll do that, and add an Arbitrary which is more exhaustive.
There was a problem hiding this comment.
Doing this has exposed a ClassCastException bug in the implementation, which I'm working through now.
|
I left a couple of superficial comments. To me, it's a bit too magical to validate eyeball, I think making all relevant tests more robust (by converting them to scalacheck) would help. I am also curious about the benchmarks. |
1afce03 to
c428c45
Compare
c428c45 to
92b6edc
Compare
|
@kailuowang I did some basic benchmarks. A right-associated call tree with 50000 I also converted the tests I thought were appropriate to scalacheck. |
Perfect 🎉 💃 |
| implicit def catsLawsArbitraryForReaderWriterStateT[F[_]: Applicative, E, L, S, A](implicit F: Arbitrary[(E, S) => F[(L, S, A)]]): Arbitrary[ReaderWriterStateT[F, E, L, S, A]] = | ||
| Arbitrary(F.arbitrary.map(ReaderWriterStateT(_))) | ||
|
|
||
| implicit def catsLawsArbitraryForListNatTrans: Arbitrary[List ~> List] = |
There was a problem hiding this comment.
These two arbitrary instances seems a bit too, well, arbitrary and limited to be included in discipline for general uses. (actually the second one might be unused according to the codcov), how about we move them into the tests?
There was a problem hiding this comment.
I'll put the used one into FreeApplicativeTests.
|
Thanks. The only minor comment left from my side is the |
|
Oh wow, thought I fixed that a while ago. Done. |
| } | ||
|
|
||
| implicit def freeArbitrary[F[_], A](implicit F: Arbitrary[F[A]], FF: Arbitrary[(A, A) => A], A: Arbitrary[A]): Arbitrary[FreeApplicative[F, A]] = | ||
| Arbitrary(freeGen[F, A](2)) |
There was a problem hiding this comment.
Sorry I meant to ask this last time but somehow lost it. Did you try maxDepth larger than 2? The main reason I ask here is that it seemed to me that you were preparing for testing maxDepth more than 2.
There was a problem hiding this comment.
Yeah I was, I forgot to raise it again after lowering.
kailuowang
left a comment
There was a problem hiding this comment.
👍 It's a bit risky but the gain is substantial.
|
@peterneyens @johnynek since you two are the only other maintains left around, got some time to review this one? It would nice to be included in the MF release. |
|
This indeed feels a bit magical. I played around a bit to get a feel what is going on and ended up refactoring See edmundnoble/cats@stacksafefreeap...peterneyens:stacksafefreeap-peter |
|
@peterneyens Wow, thank you, this is really readable. It looks like it has to be noticeably less performant than the imperative implementation (extra intermediate list which is appended to the right and extra tuple allocation introduced while reassociating an |
|
Thanks for the improved documentation @edmundnoble. Given the considerable performance improvements and the added stack safety, lets merge this as is, so we don't have to hold the 1.0.0-MF release any longer 👍 (Looks like we need to fix some conflicts first though). We can look if we can clean up the |
|
merging with 2 sign-offs |
Port from JS, from @safareli's implementation. It's stack-safe, I just need to benchmark and comment it.
Fixes #1151.