Hello!
I've been through the tutorial, and looked a bit at the basic-cli examples in the repo, but am struggling to get a handle on (among other things) Tasks. I'm starting Advent of Code (I know there's a dedicated stream, but this seems too basic and generic to fit there), and my first tiny goal is simply reading a text file into a (what I would normally call 'variable' but I think in roc is a) 'def' (same term for variable and function? because in each case it's an expression that gets evaluated to a value?).
I don't really get why tasks are a special thing with special syntax, and need for await and attempt usage, rather than just being able to use a sequence of assignments, of Result type.
So I'm looking at something like:
getLedger : Str -> Str
getLedger = \filepath ->
attempt (File.readUtf8 (Path.fromStr filepath)) \result ->
when result is
Err err -> "UH OH"
Ok data -> data
But that's not right, because I'm apparently getting InternalTask.Task c d
at the end of it, not a Str
. I don't know what that kind of Task
is, I thought Task
wasn't part of roc internals. So I'm looking at the attempt
docs from the basic-cli platform:
attempt : Task a b, Result a b -> Task c d -> Task c d
So that's saying attempt
takes a Task
parameter, and . . . a function (?) that itself takes a Result
and returns a Task
, and then the attempt
function returns a Task
? And that returned task has two payload values... and in this case a
is maybe the Path
type from the platform, and b
is maybe a union of error types, and then I realize that I don't know how to match properly on this and can't keep track of what all these single letters mean, and my brain suddenly feels very tired.
So I think I will take a break and re-read the tutorial later, but welcome any tips regarding my many misunderstandings, and any examples of Task... unwrapping/handling that is even simpler than those in the tutorial and the basic-cli example.
Someone else can probably answer this better/more theoretically, but I will try to give a general answer.
The simplified direct answer first:
Roc is a pure functional language that is not allowed to have side effects. Reading a file in most languages is a a side effect. If Roc could just read a file and return the result, it would no longer be pure and would lose the many benefits that come with being a pure language.
Instead of performing side effects, Roc returns a chain of Tasks. The platform then is responsible for executing the chain of tasks and calling the roc callbacks with the data that it loads.
Your understanding of attempt
is correct - it's saying "give me a Task
that produces an a
or an error b
. Also, once I evaluate the task at runtime and get its Result, which is either the value a
or the error b
, give me a way to transform that into another Task I can run, that produces any other value c
or error d
. And I'll give you back a Task to chain those two operations together"
In the case of getLedger
, for example, you want to read a file. This means that you want to return a Task
that can latter be chained from and used. It could be written like (note untested code):
getLedger : Str -> Task Str [] # No error type because we turn the error case to the "UH OH" string.
getLedger = \filepath ->
attempt (File.readUtf8 (Path.fromStr filepath)) \result ->
when result is
Err err -> Task.succeed "UH OH"
Ok data -> Task.succeed data
getLedger
is now a function that takes a string and returns a Task
that contains a string.
This can now be used in some other function. Something like:
printLedger : {} -> Task {} []
printLedger = \{} ->
await ( getLedger "ledger.txt" ) \data ->
Stdout.line data
Eventually, this all has to bubble up to main, which will return a task to the platform to get executed.
amazing, thank you. I read this and will read it again when I'm back at a computer.
Hello all!
I wanted to try Roc for the Advent of Code, and ran into an issue trying to run the Hello world:
roc dev
── FILE NOT FOUND ──────────────────────────────────────────────── UNKNOWN.roc ─
I am looking for this file, but it's not there:
https://github.com/roc-lang/basic-cli/releases/download/0.1.1/zAoiC9xtQPHywYk350_b7ust04BmWLW00sjb9ZPtSQk.tar.br
Is the file supposed to be there? Maybe there is a typo in the file
name?%
apparently there is a copy between file systems that does not work on mac? there is a thread with details somewhere
this call fails https://github.com/roc-lang/roc/blob/2a27d3c05f7974adf87e782704eab8d43c80652e/crates/packaging/src/cache.rs#L74
here is the thread https://roc.zulipchat.com/#narrow/stream/358903-Advent-of-Code/topic/Setting.20up.20environment.20.28nix.29/near/313301198
@Folkert de Vries I don't think there is anything wrong with that call. I believe this is because @Jordane Grenat is using a MacOS x86_64 nightly release. Those have been lagging behind due to an unresolved test failure.
@Jordane Grenat I've posted a workaround here: https://github.com/roc-lang/roc/issues/4655
Last updated: Jul 06 2025 at 12:14 UTC