Task
Task ok err
A Task represents an effect; an interaction with state outside your Roc program, such as the terminal's standard output, or a file.
forever : Task a err -> Task * err
Run a task that never ends. Note that this task does not return a value.
loop : state, (state -> Task [ Step state, Done done ] err) -> Task done err
Run a task repeatedly, until it fails with err
or completes with done
.
ok : a -> Task a *
Create a task that always succeeds with the value provided.
# Always succeeds with "Louis" getName : Task.Task Str * getName = Task.ok "Louis"
err : a -> Task * a
Create a task that always fails with the error provided.
# Always fails with the tag `CustomError Str` customError : Str -> Task.Task {} [CustomError Str] customError = \err -> Task.err (CustomError err)
attempt : Task a b, (Result a b -> Task c d) -> Task c d
Transform a given Task with a function that handles the success or error case and returns another task based on that. This is useful for chaining tasks together or performing error handling and recovery.
Consider a the following task;
canFail : Task {} [Failure, AnotherFail, YetAnotherFail]
We can use attempt
to handle the failure cases using the following;
result <- canFail |> Task.attempt when result is Ok Success -> Stdout.line "Success!" Err Failure -> Stdout.line "Oops, failed!" Err AnotherFail -> Stdout.line "Ooooops, another failure!" Err YetAnotherFail -> Stdout.line "Really big oooooops, yet again!"
Here we know that the canFail
task may fail, and so we use
Task.attempt
to convert the task to a Result
and then use pattern
matching to handle the success and possible failure cases.
await : Task a b, (a -> Task c b) -> Task c b
Take the success value from a given Task
and use that to generate a new Task
.
For example we can use this to run tasks in sequence like follows;
# Prints "Hello World!\n" to standard output. {} <- Stdout.write "Hello "|> Task.await {} <- Stdout.write "World!\n"|> Task.await Task.ok {}
onErr : Task a b, (b -> Task a c) -> Task a c
Take the error value from a given Task
and use that to generate a new Task
.
# Prints "Something went wrong!" to standard error if `canFail` fails. canFail |> Task.onErr \_ -> Stderr.line "Something went wrong!"
map : Task a c, (a -> b) -> Task b c
Transform the success value of a given Task
with a given function.
# Succeeds with a value of "Bonjour Louis!" Task.ok "Louis" |> Task.map (\name -> "Bonjour \(name)!")
mapErr : Task c a, (a -> b) -> Task c b
Transform the error value of a given Task
with a given function.
# Ignore the fail value, and map it to the tag `CustomError` canFail |> Task.mapErr \_ -> CustomError
fromResult : Result a b -> Task a b
Use a Result among other Tasks by converting it into a Task
.
batch : Task a c -> Task (a -> b) c -> Task b c
Apply a task to another task applicatively. This can be used with
ok
to build a Task
that returns a record.
The following example returns a Record with two fields, apples
and
oranges
, each of which is a List Str
. If it fails it returns the tag
NoFruitAvailable
.
getFruitBasket : Task { apples : List Str, oranges : List Str } [NoFruitAvailable] getFruitBasket = Task.ok { apples: <- getFruit Apples |> Task.batch, oranges: <- getFruit Oranges |> Task.batch, }
result : Task ok err -> Task (Result ok err) *
Transform a task that can either succeed with ok
, or fail with err
, into
a task that succeeds with Result ok err
.
This is useful when chaining tasks using the !
suffix. For example
# Path.roc checkFile : Str -> Task [Good, Bad] [IOError] # main.roc when checkFile "/usr/local/bin/roc" |> Task.result! is Ok Good -> "..." Ok Bad -> "..." Err IOError -> "..."