Skip to content
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

List's traverse method was applying effects in reverse. #142

Merged
merged 3 commits into from
Feb 10, 2015

Conversation

non
Copy link
Contributor

@non non commented Feb 8, 2015

This commit fixes this issue (which had to do with passing
arguments to G.map2 in the wrong order) and adds a regression
test to be sure we don't accidentally mess this up in the
future.

Fixes #140

Review by @refried et al.

This commit fixes this issue (which had to do with passing
arguments to G.map2 in the wrong order) and adds a regression
test to be sure we don't accidentally mess this up in the
future.
@non non added the in progress label Feb 8, 2015
@mpilquist
Copy link
Member

👍

// test sequence order using a contrived, unsafe state monad.
//

test("#140: confirm sequence order") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we make the same test on List[Option[Int]]?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah it should be possible.

@ceedubs
Copy link
Contributor

ceedubs commented Feb 9, 2015

I think this implementation of traverse is problematic when side effects are in play and should be executed in order. This is a problem even if the side effects are properly housed within something like IO or Task.

Example with scalaz's Task:

scala> traverse(List(1, 2, 3))(i => Task{println(i); i})
res2: scalaz.concurrent.Task[List[Int]] = scalaz.concurrent.Task@3b4c8039

scala> res2.run
3
2
1
res3: List[Int] = List(1, 2, 3)

I don't think you can rely on running side effects in a map call in the general case.

@non
Copy link
Contributor Author

non commented Feb 9, 2015

I don't think this is about side-effects, but just about the order in which the monad instances (which constrain effects) are composed, right?

EDIT: If you add a println to the alloc method in the test you'll see that things are printed in the "right" order.

@wedens
Copy link
Contributor

wedens commented Feb 9, 2015

scalaz/scalaz#886 discussion in scalaz

@non
Copy link
Contributor Author

non commented Feb 9, 2015

The reason Scalaz hits this problem is because they need to reverse the list to do a foldLeft. Since we are building up a result in ListBuffer we can build a result directly with foldLeft so we don't have the same issue.

That said, I agree that side-effecting during the fold is a bad idea -- the reason to avoid reversing is to minimize garbage IMO.

@ceedubs
Copy link
Contributor

ceedubs commented Feb 9, 2015

@wedens I would consider my example different than the one you have linked because I'm not using traverse directly for side effects. I'm traversing into Task (so basically IO), which as far as I know is the standard way to sequence a list of side-effecting evaluations.

@non sorry I'm not sure I completely understand your response. Are you agreeing that this is an issue, or does it not seem like a problem to you?

I have no qualms about local side effects for performance reasons. I just am not sure that you can do side effects (without using IO or something like it) in an arbitrary Applicative's map2 method in a reliable way.

This helps make it a bit more obvious that monadic effect
order and side-effect order are the same.
mpilquist added a commit that referenced this pull request Feb 10, 2015
List's traverse method was applying effects in reverse.
@mpilquist mpilquist merged commit 501a4f0 into master Feb 10, 2015
@non non deleted the bug/fix-list-traverse-order branch February 18, 2015 22:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

is sequence applying effects in backwards order?
5 participants