-
-
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
replicateA_, replicateM, replicateM_ #3705
Changes from all commits
2127562
203ed45
2f9a258
aa7694d
221ccf6
c695ff8
f8f1ef8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -67,6 +67,32 @@ import scala.annotation.implicitNotFound | |||
def replicateA[A](n: Int, fa: F[A]): F[List[A]] = | ||||
Traverse[List].sequence(List.fill(n)(fa))(this) | ||||
|
||||
/** | ||||
* Given `fa` and `n`, apply `fa` `n` times but discard the results. | ||||
* | ||||
* Example: | ||||
* {{{ | ||||
* scala> import cats.data.State | ||||
* | ||||
* scala> type Counter[A] = State[Int, A] | ||||
* scala> val increment: Counter[Unit] = State.modify(_ + 1) | ||||
* scala> val get: Counter[Int] = State.get | ||||
* scala> val increment5AndGet: Counter[Int] = Applicative[Counter].productR( | ||||
* | Applicative[Counter].replicateA_(5, increment), | ||||
* | get | ||||
* | ) | ||||
* scala> increment5AndGet.run(0).value | ||||
* res0: (Int, Int) = (5,5) | ||||
* }}} | ||||
*/ | ||||
def replicateA_[A](n: Int, fa: F[A]): F[Unit] = | ||||
def go(x: Int, step: F[Unit]): F[Unit] = { | ||||
if(x == 0) step | ||||
else go(x - 1, this.productR(fa, step)) | ||||
} | ||||
go(n, this.pure(())) | ||||
} | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Stray closing brace:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I'm missing an opening brace. I don't know how I didn't catch that. |
||||
|
||||
/** | ||||
* Compose an `Applicative[F]` and an `Applicative[G]` into an | ||||
* `Applicative[λ[α => F[G[α]]]]`. | ||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -144,6 +144,15 @@ import scala.annotation.implicitNotFound | |
|
||
tailRecM(branches.toList)(step) | ||
} | ||
|
||
def replicateM[A](n: Int, fa: F[A]): F[List[A]] = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for any lawful monad, these are exactly the same as replicateA aren't they? I am opposed to adding a function that is only different when the monad is not lawful. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, but it does not have the overhead of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. People can override for efficiency but my opinion is that we should not have duplicative functions that are equivalent in general. Secondly, generally I think we should not trade stack safety for performance since lack of stack safety makes the library randomly fail when sizes get a bit larger. I think we should have it be as fast as possible that is also stack safe, IMO. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good. Should I remove replicateM or just alias it? Should I override replicateM with this version in StackSafeMonad? |
||
if (n == 0) this.pure(Nil) | ||
else this.flatMap(fa)(head => this.flatMap(replicateM(n - 1, fa))(tail => head :: tail)) | ||
|
||
def replicateM_[A](n: Int, fa: F[A]): F[Unit] = | ||
if (n == 0) this.pure(()) | ||
else this.flatMap(fa)(_ => replicateM_(n - 1, fa)) | ||
|
||
} | ||
|
||
object Monad { | ||
|
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.
nit:
pure(())
is the same asunit
.nit: if we keep this implementation, I'd like to add the tailrec annotation.
instead of using
fa
can we do make:val fvoid = void(fa)
outside of def go, and use that?I still want to express this function in a stack safe way if we can.
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 was thinking about adding
@tailrec
but didn't know if it was used elsewhere. Will do.