-
Notifications
You must be signed in to change notification settings - Fork 601
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
Traversing a list/vector is in reverse #746
Comments
What is the Example with Scalaz: scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
scala> List(1, 2, 3).traverse { i =>
| println(i) // side effect!
| Option(i)
| }
3
2
1
res0: Option[List[Int]] = Some(List(1, 2, 3))
scala> import scalaz.concurrent.Task
import scalaz.concurrent.Task
scala> def printOption(i: Int): OptionT[Task, Int] = {
| val task = Task(println(i)) *> Task.now(i)
| OptionT(task.map(Option(_)))
| }
printOption: (i: Int)scalaz.OptionT[scalaz.concurrent.Task,Int]
scala> List(1, 2, 3).traverseU(printOption).run.unsafePerformSync
1
2
3
res3: Option[List[Int]] = Some(List(1, 2, 3)) |
The
|
@AdamChlupacek This is essentially dependent on the @adelbertc If the traversal is done in an inverse order, the inner applicative may be sequenced incorrectly. Even in pure computations, this is observable. It is irrelevant only for commutative monads, of which |
@djspiewak I am using the instance from fs2.util.Traverse |
Oh, fs2 defines Both the |
This is a bug. Traverse should be implemented with a stack safe right fold,
|
Actually I am looking at this and the traverse instance does not look Maybe the applicative instance is backward for the type you are using?
|
@pchiusano Are you sure the effects are done in the right order? I don't see anything in the composition which changes the ordering, only the associativity. Thus, the |
Am on my phone but it looks like the definition is an inline stack safe (tl,hd) => G.ap(f(hd))(G.map(tl)(tl => (b: B) => b +: tl)) So notice that the hd effect is run before the tl effect (assuming the
|
@pchiusano I am using the fs2.Task, so I am pretty sure it is not reversed in my applicative instance. Now If I am reading it right, for Task the Applicative is implemented in
from this I would assume that we first get the tl effect and hd effect afterwards? |
@AdamChlupacek yeah I think you've got it! Honestly, it doesn't matter too much what order it's expected that Here are some possible things we could do to fix:
We could do some combination of these, too. 1) for now, with suitable warnings in the release notes / announcement, and then 2) in the next release series, which may not be for a while. Reason that sequencing the
The only thing that is confusing is the scala> val T = implicitly[Monad[Task]]
T: fs2.util.Monad[fs2.Task] = Effect[Task]
scala> T.ap(Task.now(10: Int))(Task.now(i => i))
<console>:19: error: missing parameter type
T.ap(Task.now(10: Int))(Task.now(i => i)) |
Not sure how much it'd help but here are related tickets to how we dealt with it in Cats: |
Fixed in 0.9 by changing the order of evaluation of default implementation of In 1.0, we'll change the parameter definition order. |
Hello,
I have been traversing a List using:
And I have encountered issue that the order the list get traversed in is 3, 2, 1, which in my opinion is a bit unintuitive. I would find the order 1, 2, 3 to be more intuitive. I do understand that the motivation behind the reverse traversing is so that we only prepend to the result list, but this way I have to do 2 reverses to traverse the list in the order I want.
Instead I propose to traverse the list in the order 1, 2, 3 while still prepending to the head of the result and then reverse the result list.
Adam Chlupacek
The text was updated successfully, but these errors were encountered: