In Eric Torreborre’s blogpost on the paper Essence of the Iterator Pattern, he describes how the cartesian product of a traverse is also a traverse.
Can anyone show me an example of this using the scalaz library as I can’t figure it out. Let’s say the problem is that, for a List[Int] I want to provide both of:
- The
Intsum of the elements in the list - A
List[String]the elements of which are created by appending the “Z” to the String representation of theInts
My understanding is that I can do this using traverse but in such a way as to only actually traverse my structure once, unlike this solution:
val xs = List(1, 2, 3, 4)
val (sum, strings) = (xs.sum, xs map (_.toString + "Z"))
NOTE 1 – I know that there are other ways of doing this and that I neither need traverse for this example, and nor is traverse even necessarily the clearest way to solve it. I am, however, trying to understand traverse, so am really looking for the answer to the question as stated
EDIT – thanks to missingfaktor below for showing how to do this using State. I guess what I want to know is how I can compose the two independent calculations. For example; my functions are notionally as follows:
val shape = (_ : List[Int]) map (_.toString + "Z")
val accum = (_ : List[Int]).sum
I want to have these mechanisms of accumulation independently of one another and then choose whether to traverse my List[Int] using either or both of them. I imagined some code a bit like this:
xs traverse shape //A List[String]
xs traverse accum //An Int
xs traverse (shape <x> accum) //The pair (List[String], Int)
Eric implies that this is possible but I don’t get how to do it ~ i.e. I don’t see how to define shape and accum in such a way as that they can be composed, nor how to compose them.
NOTE 2 that shape and accum are not meant to literally be the functions with the signatures as above. They are expressions which have the type necessary to perform the above traversals.
I’m adding my own answer, building on Jason’s one, to show different ways of traversing the list:
I think that the last example shows what you’re after: 2 independently defined functions which can be composed to do just one traversal.