Stream: beginners

Topic: ✔ Recursive effectful function


view this post on Zulip Claude Précourt (Oct 26 2025 at 17:48):

Hello!

I am writing a very simple tool which needs to walk a directory structure but I've hit a road block. I get this error :

This 2nd argument to |> has an unexpected type:

27│                      Ok children -> children |> List.join_map(|child| walk_hierarchy!(child, depth + 1, hierarchy))
                                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The argument is an anonymous function of type:

    Path.Path => List Str

But |> needs its 2nd argument to be:

    InternalPath.InternalPath -> List Str

and I suspect that the Path vs InternalPath isn't the issue but rather the fact that I should somehow make my "walk_hierarchy!" function non-effectful?

And this is my little bit a code :

app [main!] {
    cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.19.0/Hj-J_zxz7V9YurCSTFcFdu6cQJie4guzsPMUi5kBYUk.tar.br",
}

import cli.Arg
import cli.Stderr
import cli.Dir
import cli.Path

main! = |args|
    when List.get(args, 1) is
        Ok arg ->
            root_path = Arg.display(arg) |> Path.from_str
            _hierarchy = walk_hierarchy!(root_path, 0, [])
            Ok {}
        Err OutOfBounds ->
            _ = Stderr.line!("Usage: archiveux PATH")
            Ok {}

walk_hierarchy! : Path.Path, U64, List Str => List Str
walk_hierarchy! = |root, depth, hierarchy|
    current_level = [Str.repeat("\t", depth) |> Str.concat(Path.display(root))]
    subs = when Path.is_dir!(root) is
        Ok is_dir ->
            if is_dir then
                when Path.list_dir!(root) is
                    Ok children -> children |> List.join_map(|child| walk_hierarchy!(child, depth + 1, hierarchy))
                    Err _ -> []
            else
                current_level
        Err _ -> []
    List.concat(hierarchy, subs)

Any hint would be welcome!

view this post on Zulip Brendan Hansknecht (Oct 26 2025 at 18:04):

The issue is fundamentally that join_map does not accept effectful functions. It would need to be join_map! to do so.

There likely should be an effectful version of that function

view this post on Zulip Brendan Hansknecht (Oct 26 2025 at 18:05):

Easiest solution is to write your own for now:

join_map! : List a, (a => List b) => List b
join_map! = |list, mapper|
    List.walk!(list, [], |state, elem| List.concat(state, mapper(elem)))

view this post on Zulip Claude Précourt (Oct 26 2025 at 18:08):

Ha! Great, thanks! Or maybe to use walk! instead ?

view this post on Zulip Claude Précourt (Oct 26 2025 at 18:13):

Thank you so much! Worked like a charm. Just needed to add an exclamation point to the mapper arg to get rid of a warning.

view this post on Zulip Notification Bot (Oct 26 2025 at 18:29):

Claude Précourt has marked this topic as resolved.

view this post on Zulip Anton (Oct 27 2025 at 11:51):

I added List.join_map! in #8337

view this post on Zulip Claude Précourt (Oct 27 2025 at 15:41):

As if I didn't love this language enough already! :face_holding_back_tears:

view this post on Zulip Anton (Oct 27 2025 at 15:42):

Thanks :)
The new addition will be in tomorrow's nightly


Last updated: Nov 09 2025 at 12:14 UTC