-
-
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
Tail-recursive replicateA
#4234
Conversation
|
||
map(loop(n))(_.toList) | ||
map(loop(one, n, pure(Chain.empty)))(_.toList) |
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 have a minor anxiety about the extra cost of the map2(a, pure(Chain.empty))(_.concat(_))
being the same as a
.
What if we cheat:
val emptyF = pure(Chain.empty)
def concat(left: F[Chain[A]], right: F[Chain[A]]): F[Chain[A]] =
if (right eq emptyF) left else map2(left, right)(_.concat(_))
@tailrec def loop(fa: F[Chain[A]], n: Int, acc: F[Chain[A]]): F[Chain[A]] =
if (n == 1) concat(fa, acc)
else
// n >= 2
// so (n >> 1) >= 1 and we are allowed to call loop
loop(
map2(fa, fa)(_.concat(_)),
n >> 1,
if ((n & 1) == 1) concat(fa, acc) else acc
)
So we can leverage the law that concat(a, pure(Chain.empty)) == 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.
What if we wrote it as loop(one, n - 1, one)
instead?
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.
yeah, I think that works... but for replicateA_
I think we need to rewrite so that we only entire the loop in the n >= 2
case as we do here.
loop( | ||
productR(fa)(fa), | ||
n >> 1, | ||
if ((n & 1) == 1) productR(acc)(fa) else acc |
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.
same comment here about leveraging productR(unit)(a) == a
to avoid doing a needless productR(fa)(unit)
Yet another follow-up :) see #4233 (comment).
It doesn't seem more complex to me than the recursive implementation since it's the same basic algorithm, but I don't feel that strongly. Maybe a benchmark could make it more interesting.