Stream: beginners

Topic: convert list of task to task of list


view this post on Zulip Shritesh Bhattarai (Dec 10 2022 at 21:26):

Is there a way to convert a List (Task a err) into Task (List a) err ? I have seen mention of a chain function in the chat logs but couldn't find an implementation of it.

view this post on Zulip Folkert de Vries (Dec 10 2022 at 21:44):

this should do it

map2 : Task a err, Task b err, (a, b -> c) -> Task c err
map2 = \task1, task2, mapper ->
    task1 |> Task.await \value1 ->
        task2 |> Task.map \value2 ->
            mapper value1 value2

traverse : List a, (a -> Task b err) -> Task (List b) err
traverse = \list, f ->
    walker : Task (List b) err, a -> Task (List b) err
    walker = \state, element -> map2 state (f element) List.append

    initialState = Task.succeed (List.withCapacity (List.len list))
    List.walk list initialState walker

combine : List (Task a err) -> Task (List a) err
combine = \list -> traverse list (\x -> x)

view this post on Zulip Folkert de Vries (Dec 10 2022 at 21:45):

it is inefficient though, map2 could be implemented more efficiently but we don't provide that at the moment

view this post on Zulip Shritesh Bhattarai (Dec 10 2022 at 21:52):

Thanks. It works!

view this post on Zulip Shritesh Bhattarai (Dec 10 2022 at 21:59):

Welp. It segfaults for a large list.

view this post on Zulip Folkert de Vries (Dec 10 2022 at 22:01):

that kind of makes sense? it recursive builds up a task

view this post on Zulip Folkert de Vries (Dec 10 2022 at 22:02):

that is the inefficiency

view this post on Zulip Folkert de Vries (Dec 10 2022 at 22:02):

how large is large though?

view this post on Zulip Shritesh Bhattarai (Dec 10 2022 at 22:04):

90000

view this post on Zulip Folkert de Vries (Dec 10 2022 at 22:06):

ok, is that a problem for an actual program you are trying to run?

view this post on Zulip Folkert de Vries (Dec 10 2022 at 22:07):

or phrased differently: is this blocking you in practice?

view this post on Zulip Shritesh Bhattarai (Dec 10 2022 at 22:08):

I'm writing a raytracer for fun. I wanted to play around with effects and decided to do random numbers using effects but I guess I can seed the rng once and thread the rng around on the Roc side.

view this post on Zulip Shritesh Bhattarai (Dec 10 2022 at 22:16):

Anyway, I just pushed the code up to github if anyone wants to take a look: https://github.com/shritesh/raytrace.roc/blob/766c4b8f2d0a0bc9b6669e168ec9f86cded11b21/Raytrace.roc. I already have a RNG.roc that used the "threading the rng" model and it works as expected. The size of the generated image is defined in Camera.roc. Image width of 100 seems to not overflow the stack.

view this post on Zulip Brendan Hansknecht (Dec 10 2022 at 22:38):

This is all built with optimizations(i assume so, just double checking)? Also, if it is useful (probably outdated), but there is https://github.com/JanCVanB/roc-random

view this post on Zulip Shritesh Bhattarai (Dec 10 2022 at 23:09):

I did look into that but wanted to do my own as a learning exercise. I have just updated my RNG to take a function with the new RNG and the value as params and it feels very ergonomic.


Last updated: Jul 06 2025 at 12:14 UTC