-
-
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 State/StateT #302
Add State/StateT #302
Conversation
To avoid stack overflows, a couple design choices were made that make State more complicated than it seems like it should be. State wraps F[S => F[(S, A)]] instead of the more familiar S => F[(S, A)]. This allows for effective trampolining. State[S, A] is a type alias for StateT[Trampoline, S, A] to avoid stack overflows that are easy to hit if Id is used instead of Trampoline. State is currently in its own module because it depends on Free (for trampolining) but doesn't seem to belong in the Free module. Since it's tough to avoid trampolining in FP Scala, we may want to reconsider whether Free should be in core. There is a brief ScalaDoc comment on StateT, but a proper markdown file should probably be created. If this gets merged, I can send a follow-up PR with some more documentation.
This is embarrassing. One of my more recent changes appears to have made the test not compile and I guess I didn't run the tests again before submitting. Will fix :( |
LGTM, plus I like the runX names. |
/** | ||
* Run with `S`'s empty monoid value as the initial state. | ||
*/ | ||
def runEmpty(implicit S: Monoid[S], F: FlatMap[F]) = run(S.empty) |
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 is missing the return type.
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 catch. Pushed a new commit that fixes the three instances.
And also simplify the StateT.map implementation.
Looks great (application of the state function now cannot be done recursively without passing through |
Looks great to me. 👍 |
lazy val state = project.dependsOn(macros, core, free, tests % "test -> test") | ||
.settings(moduleName := "cats-state") | ||
.settings(catsSettings) | ||
.settings(noPublishSettings) |
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.
Is there a reason not to publish this?
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.
Oh, good catch. I would be fine publishing it.
Want to submit a small PR fixing this?
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.
Fixed by #312
Fixes #122.
To avoid stack overflows, a couple design choices were made that make
State more complicated than it seems like it should be.
State wraps F[S => F[(S, A)]] instead of the more familiar S => F[(S, A)]. This allows for effective trampolining.
State[S, A] is a type alias for StateT[Trampoline, S, A] to avoid stack
overflows that are easy to hit if Id is used instead of Trampoline.
State is currently in its own module because it depends on Free (for
trampolining) but doesn't seem to belong in the Free module. Since it's
tough to avoid trampolining in FP Scala, we may want to reconsider
whether Free should be in core.
There is a brief ScalaDoc comment on StateT, but a proper markdown file
should probably be created. If this gets merged, I can send a follow-up
PR with some more documentation.