Repository navigation
Add TaskResult.ofCatchTask - #353
Conversation
Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds TaskResult.ofCatchTask to handle the common pattern of lifting a throwable Task<'T> into Task<Result<'T, exn>> by catching exceptions and mapping them to the Error case. This addresses a gap where the existing TaskResult.ofTask wraps values in Ok without catching exceptions, leading to unexpected exception propagation.
Changes:
- Add
ofCatchTaskfunction that catches task exceptions and maps them toError, similar to howAsyncResult.ofTaskworks - Update
ofTaskdocumentation to clarify it doesn't catch exceptions and cross-reference the new function - Add comprehensive tests covering success and exception scenarios
- Add complete documentation with examples and function signatures
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/FsToolkit.ErrorHandling/TaskResult.fs | Adds ofCatchTask implementation using Task.catch |> Task.map Result.ofChoice pattern; adds XML documentation to ofTask clarifying exception behavior |
| tests/FsToolkit.ErrorHandling.Tests/TaskResult.fs | Adds two test cases: one verifying successful tasks return Ok, another verifying throwing tasks return Error with captured exception |
| gitbook/taskResult/ofTask.md | Adds note clarifying ofTask does not catch exceptions and links to ofCatchTask |
| gitbook/taskResult/ofCatchTask.md | New documentation page describing the function with signature and examples |
| gitbook/SUMMARY.md | Adds link to ofCatchTask documentation in alphabetical order under Transforms section |
| @@ -25,3 +27,4 @@ let result = TaskResult.ofTask (task { return 42 }) | |||
| let result = TaskResult.ofTask (task { return System.Exception("error") }) | |||
| // task { return Error (System.Exception("error")) } | |||
There was a problem hiding this comment.
This example is incorrect. Since ofTask does not catch exceptions and just wraps the value in Ok, returning a System.Exception value would result in Ok(System.Exception("error")), not Error(...). This example should either be removed or replaced with a correct example that shows successful wrapping of a value in Ok.
| // task { return Error (System.Exception("error")) } | |
| // task { return Ok (System.Exception("error")) } |
There was a problem hiding this comment.
Fixed in 2cba7f5 — corrected the comment to Ok (System.Exception("error")) since ofTask just wraps the value in Ok without catching anything.
There was a problem hiding this comment.
@copilot this is not acceptable. You need to show the error case properly.
There was a problem hiding this comment.
Fixed in 46b4928 — Example 2 now shows that a throwing task has its exception propagate out (not caught/wrapped in Error).
TheAngryByrd
left a comment
There was a problem hiding this comment.
@copilot, review other copilot comments
Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com>
Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com>
- [Add IAsyncEnumerable support to task computation expressions](#347) Credits @Copilot - [Add `valueTaskValueOption` CE for `ValueTask<'T voption>` computation expressions](#348) Credits @Copilot - [Add `cancellableValueTaskOption` and `cancellableValueTaskResult` CEs for IcedTasks](#349) Credits @Copilot - [Add `Source` overloads to `taskResultOption` CE for interop with `Result`, `TaskResult`, `Option`, `Task`, and `Async`](#351) Credits @Copilot - [Add `requireSomeWith` and `requireNoneWith` for lazy error evaluation](#352) Credits @Copilot - [Add `TaskResult.ofCatchTask`](#353) Credits @Copilot - [Add comprehensive gitbook documentation for all public API surface](#354) Credits @Copilot
- [Add IAsyncEnumerable support to task computation expressions](#347) Credits @Copilot - [Add `valueTaskValueOption` CE for `ValueTask<'T voption>` computation expressions](#348) Credits @Copilot - [Add `cancellableValueTaskOption` and `cancellableValueTaskResult` CEs for IcedTasks](#349) Credits @Copilot - [Add `Source` overloads to `taskResultOption` CE for interop with `Result`, `TaskResult`, `Option`, `Task`, and `Async`](#351) Credits @Copilot - [Add `requireSomeWith` and `requireNoneWith` for lazy error evaluation](#352) Credits @Copilot - [Add `TaskResult.ofCatchTask`](#353) Credits @Copilot - [Add comprehensive gitbook documentation for all public API surface](#354) Credits @Copilot
- [Add IAsyncEnumerable support to task computation expressions](#347) Credits @Copilot - [Add `valueTaskValueOption` CE for `ValueTask<'T voption>` computation expressions](#348) Credits @Copilot - [Add `cancellableValueTaskOption` and `cancellableValueTaskResult` CEs for IcedTasks](#349) Credits @Copilot - [Add `Source` overloads to `taskResultOption` CE for interop with `Result`, `TaskResult`, `Option`, `Task`, and `Async`](#351) Credits @Copilot - [Add `requireSomeWith` and `requireNoneWith` for lazy error evaluation](#352) Credits @Copilot - [Add `TaskResult.ofCatchTask`](#353) Credits @Copilot - [Add comprehensive gitbook documentation for all public API surface](#354) Credits @Copilot Remove AutoGPT subproject reference
- [Add IAsyncEnumerable support to task computation expressions](#347) Credits @Copilot - [Add `valueTaskValueOption` CE for `ValueTask<'T voption>` computation expressions](#348) Credits @Copilot - [Add `cancellableValueTaskOption` and `cancellableValueTaskResult` CEs for IcedTasks](#349) Credits @Copilot - [Add `Source` overloads to `taskResultOption` CE for interop with `Result`, `TaskResult`, `Option`, `Task`, and `Async`](#351) Credits @Copilot - [Add `requireSomeWith` and `requireNoneWith` for lazy error evaluation](#352) Credits @Copilot - [Add `TaskResult.ofCatchTask`](#353) Credits @Copilot - [Add comprehensive gitbook documentation for all public API surface](#354) Credits @Copilot Remove AutoGPT subproject reference
- [Add IAsyncEnumerable support to task computation expressions](#347) Credits @Copilot - [Add `valueTaskValueOption` CE for `ValueTask<'T voption>` computation expressions](#348) Credits @Copilot - [Add `cancellableValueTaskOption` and `cancellableValueTaskResult` CEs for IcedTasks](#349) Credits @Copilot - [Add `Source` overloads to `taskResultOption` CE for interop with `Result`, `TaskResult`, `Option`, `Task`, and `Async`](#351) Credits @Copilot - [Add `requireSomeWith` and `requireNoneWith` for lazy error evaluation](#352) Credits @Copilot - [Add `TaskResult.ofCatchTask`](#353) Credits @Copilot - [Add comprehensive gitbook documentation for all public API surface](#354) Credits @Copilot
- [Add IAsyncEnumerable support to task computation expressions](#347) Credits @Copilot - [Add `valueTaskValueOption` CE for `ValueTask<'T voption>` computation expressions](#348) Credits @Copilot - [Add `cancellableValueTaskOption` and `cancellableValueTaskResult` CEs for IcedTasks](#349) Credits @Copilot - [Add `Source` overloads to `taskResultOption` CE for interop with `Result`, `TaskResult`, `Option`, `Task`, and `Async`](#351) Credits @Copilot - [Add `requireSomeWith` and `requireNoneWith` for lazy error evaluation](#352) Credits @Copilot - [Add `TaskResult.ofCatchTask`](#353) Credits @Copilot - [Add comprehensive gitbook documentation for all public API surface](#354) Credits @Copilot Remove AutoGPT subproject reference
TaskResult.ofCatchTaskfunction toTaskResult.fswith doc commentsTaskResult.ofTaskclarifying it doesn't catch exceptions (with reference toofCatchTask)TaskResult.ofCatchTaskintests/FsToolkit.ErrorHandling.Tests/TaskResult.fsgitbook/taskResult/ofCatchTask.mddocumentationgitbook/taskResult/ofTask.mdto referenceofCatchTaskand show error case properly (exception propagates)gitbook/SUMMARY.mdto includeofCatchTaskreturn failwithsyntax inofCatchTaskdoc comment example (both in source and gitbook)ofTask.mdExample 2 to show that exceptions propagate (not caught)./build.sh CheckFormatCode— passesOriginal prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.