raulraja
02/01/2018, 9:43 PM/**
* Given a function which returns a G effect, thread this effect through the running of this function on all the
* values in F, returning an F<B> in a G context.
*/
fun <G, A, B> traverse(fa: HK<F, A>, f: (A) -> HK<G, B>, GA: Applicative<G>): HK<G, HK<F, B>>
It really works for anything that is nested and you need to reverse. Nesting happens because of Effects that are not resolved start stacking up as you add concerns such as Option
in this case for absence.
If you think about the Option
here as a concern, this application had several values which were in ambiguous state and the user wants to resolve the ambiguity, in this case if their values are fulfilled or not. In the case of concurrency if the op completed succesfuly or exceptionally.
So when you have a list of values which concern you, you can turn them around and create a single concern that will hold the final list of values under that concern flattening them all. The trick here is that if one of those values is not in the state you need it when traversing for example one of them was a None
it can't form a List<A>
the resulting Option<List<A>>
would be a None
.
So what is happening here is that a list of effects is getting sequenced to obtain an effect with a list of values.
Traverse/sequence and the applicative combinators are among the most valuable.
To see more examples and use cases one can imagine where some of this types may come from:
List<Validated<FormError, ?>> -> Validated<FormError, List<?>>
List<Try<Nuke>> -> Try<List<Nuke>>
List<Dsl<Endpoints>> -> Dsl<List<Endpoints>>
These types of transformations appear in most programs that have nested effects