Repository navigation
Conversation
0e67281 to
6d72e02
Compare
7c46139 to
748630c
Compare
|
@TheAngryByrd The opening objective was to address #375, but I think it makes sense to include parts of #373 in order to make that a more digestible review, but also including some preparatory work for same. There's lots of xmldoc corrections, fixing orphans and typos etc. Let me know if you need anything to change (I assume you squash merge - my history is imperfect) but for now I'll assume that this will merge relatively soon. I'll start rebasing #373 on this next. |
deb32c6 to
f5db8b2
Compare
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Pull request overview
This PR harmonizes the Result-family APIs across Result, AsyncResult, TaskResult, CancellableTaskResult, and JobResult by introducing consistent helpers (ok, either, eitherMap, bindResult, ignore) and updating tests/docs accordingly, plus a packaging workaround for FSharp.Core xml docs.
Changes:
- Added/standardized helpers (
ok,error,either,eitherMap,bindResult) across async/task/job result modules; marked legacy names (e.g.,foldResult,valueOr) as obsolete. - Made
Task.ignore/Option.ignore/Async.ignorerequire explicit type arguments and updated tests/docs to match. - Updated GitBook docs, release notes, and build props (incl.
FSharp.CoreExcludeAssets="contentfiles"workaround).
Reviewed changes
Copilot reviewed 52 out of 52 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/FsToolkit.ErrorHandling.Tests/TaskResult.fs | Renames foldResult tests to either to match new API naming. |
| tests/FsToolkit.ErrorHandling.Tests/Result.fs | Test cleanup (tuple type syntax, defaultWith test update, minor typos). |
| tests/FsToolkit.ErrorHandling.Tests/Option.fs | Updates Option.ignore tests to include explicit type arguments; fixes typos. |
| tests/FsToolkit.ErrorHandling.Tests/AsyncResult.fs | Renames foldResult tests to either for API alignment. |
| src/FsToolkit.ErrorHandling/TaskResult.fs | Adds ok/error, either, eitherMap, bindResult; refactors bind-require helpers. |
| src/FsToolkit.ErrorHandling/Task.fs | Adds RequiresExplicitTypeArguments to Task.ignore. |
| src/FsToolkit.ErrorHandling/Result.fs | Marks valueOr obsolete and forwards to defaultWith. |
| src/FsToolkit.ErrorHandling/Option.fs | Adds RequiresExplicitTypeArguments to Option.ignore. |
| src/FsToolkit.ErrorHandling/AsyncResultOptionCE.fs | Uses AsyncResult.ok for Zero; minor builder construction cleanup. |
| src/FsToolkit.ErrorHandling/AsyncResult.fs | Introduces either, obsoletes foldResult, adds bindResult, updates require-bind helpers. |
| src/FsToolkit.ErrorHandling/Async.fs | Refactors map3 implementation and adds Async.ignore with explicit type args requirement. |
| src/FsToolkit.ErrorHandling.JobResult/JobResult.fs | Adds ok/error, either, bindResult, expands map helpers, updates examples. |
| src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskResultCE.fs | Cleans up CE internals and adds either/eitherMap + obsolete alias. |
| src/Directory.Build.props | Updates copyright years; adds ExcludeAssets="contentfiles" to pinned FSharp.Core. |
| gitbook/validation/ce.md | Updates parsing example to use Option.tryParse. |
| gitbook/taskResultOption/ignore.md | Documents explicit type arguments for TaskResultOption.ignore. |
| gitbook/taskResult/ignore.md | Documents explicit type arguments for TaskResult.ignore. |
| gitbook/taskResult/foldResult.md | Updates documentation to TaskResult.either naming. |
| gitbook/task/ignore.md | Documents explicit type arguments for Task.ignore. |
| gitbook/seq/traverseResultM.md | Updates examples to use Option.tryParse/Option.defaultWith. |
| gitbook/seq/traverseResultA.md | Updates examples to use Option.tryParse. |
| gitbook/seq/sequenceResultM.md | Updates examples to use Option.tryParse. |
| gitbook/seq/sequenceResultA.md | Updates examples to use Option.tryParse. |
| gitbook/seq/partitionResults.md | Updates examples to use Option.tryParse. |
| gitbook/script.fsx | Updates parsing example to use Option.tryParse. |
| gitbook/resultOption/ignore.md | Documents explicit type arguments for ResultOption.ignore. |
| gitbook/result/map3.md | Updates parsing example to use Option.tryParse. |
| gitbook/result/map2.md | Updates parsing example to use Option.tryParse. |
| gitbook/result/ignore.md | Documents explicit type arguments for Result.ignore. |
| gitbook/result/fold.md | Renames content to Result.either semantics (doc-only rename). |
| gitbook/result/eitherFunctions.md | Fixes expected output comment for eitherMap example. |
| gitbook/option/ignore.md | Updates docs to require explicit type args; adds CE example. |
| gitbook/list/traverseResultM.md | Updates parsing example to use Option.tryParse. |
| gitbook/list/traverseResultA.md | Updates parsing example to use Option.tryParse. |
| gitbook/list/traverseJobResultM.md | Updates job parsing example to use Option.tryParse. |
| gitbook/list/traverseJobResultA.md | Updates job parsing example to use JobResult.ok/error + Option.tryParse. |
| gitbook/list/sequenceResultM.md | Updates parsing example to use Option.tryParse. |
| gitbook/list/sequenceResultA.md | Updates parsing example to use Option.tryParse. |
| gitbook/list/partitionResults.md | Updates parsing example to use Option.tryParse. |
| gitbook/jobResultOption/ignore.md | Documents explicit type arguments for JobResultOption.ignore. |
| gitbook/jobResult/ignore.md | Documents explicit type arguments for JobResult.ignore. |
| gitbook/jobResult/foldResult.md | Updates documentation to JobResult.either naming. |
| gitbook/cancellableTaskResult/ignore.md | Documents explicit type arguments for CancellableTaskResult.ignore. |
| gitbook/cancellableTaskResult/foldResult.md | Updates documentation to CancellableTaskResult.either naming. |
| gitbook/asyncResultOption/ignore.md | Documents explicit type arguments for AsyncResultOption.ignore. |
| gitbook/asyncResult/ignore.md | Documents explicit type arguments for AsyncResult.ignore. |
| gitbook/asyncResult/foldResult.md | Updates documentation to AsyncResult.either naming. |
| gitbook/asyncResult/eitherMap.md | Updates examples; adds Async.RunSynchronously; rewrites combined usage guidance. |
| gitbook/array/partitionResults.md | Updates parsing example to use Option.tryParse. |
| gitbook/SUMMARY.md | Moves navigation entries from fold/foldResult to either. |
| build/build.fs | Updates NuGet package summary wording. |
| RELEASE_NOTES.md | Adds 6.0.0-beta002 notes describing API harmonization + packaging fix. |
Suppressed comments (8)
src/FsToolkit.ErrorHandling/TaskResult.fs:1
- The generic shape of
TaskResult.eitherMapis unexpectedly restrictive: it forces the mappedOktype ('b) to be the same as the input error type (also'b).eitherMaptypically allows mappingOkandErrorindependently:Task<Result<'ok,'err>> -> Task<Result<'ok2,'err2>>. Consider changing the signature to acceptTask<Result<'a,'c>>and returnTask<Result<'b,'d>>withonSuccess: 'a -> 'bandonError: 'c -> 'd(matchingResult.eitherMapand yourJobResult.eitherMapimplementation).
src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskResultCE.fs:1 - Same issue as
TaskResult.eitherMap: this signature forces the mappedOktype to equal the input error type. To preserve the standardeitherMapshape, considerCancellableTask<Result<'a,'c>> -> CancellableTask<Result<'b,'d>>withonSuccess: 'a -> 'bandonError: 'c -> 'd.
src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskResultCE.fs:1 - The obsolete message points to
TaskResult.either, but this module definesCancellableTaskResult.either. This is likely confusing for users and should referenceCancellableTaskResult.eitherinstead.
src/FsToolkit.ErrorHandling/AsyncResult.fs:1 AsyncResult.eitherMapnow has an explicit return type but leavesonSuccess,onError, andinputuntyped. This can make the public API signature harder to read in IntelliSense and can produce less helpful type errors. Consider fully annotating it (likeJobResult.eitherMap) to clearly communicate the intendedAsync<Result<'ok,'err>> -> Async<Result<'ok2,'err2>>shape.
gitbook/task/ignore.md:1- The explicit type argument passed to
Task.ignoreappears inconsistent with the surrounding example (which indicatessavePostreturns aPostId). The ignored type argument should match the task's result type (e.g.,Task.ignore<PostId>in this example), otherwise the snippet won’t compile and may mislead users.
tests/FsToolkit.ErrorHandling.Tests/Result.fs:1 - This test is under
defaultWith Testsand callsResult.defaultWith, but the test name saysdefaultValue. Renaming the test case todefaultWith ...would better reflect what’s being tested and reduce confusion when failures occur.
src/FsToolkit.ErrorHandling/Result.fs:1 - The PR description says
valueOris removed, but the code keeps it as an obsolete alias. Either update the PR description/release notes to reflect the deprecation approach, or actually removevalueOrif the intent is a hard removal in this version.
src/FsToolkit.ErrorHandling/TaskResult.fs:1 - New public surface area (
TaskResult.bindResult, plus the neweither/eitherMaphelpers in this module) doesn’t appear to have corresponding tests in the diffs. Since this repo has a dedicated test project for these modules, adding direct unit tests forbindResultandeitherMap(both Ok and Error paths) would help prevent regressions and validate the intended type behavior.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
a82aa59 to
ff43e76
Compare
f4b9bee to
c67a133
Compare
|
OK, test coverage is complete per clanky and manual review |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The critical JobResult test entry-point issue and moderate incomplete JobResult API remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (11)
Qualify runTestsInAssemblyWithCLIArgs with Tests · New Document the CancellableTask option input wrapper · New Correct CancellableValueTaskOption.either signature · New Document the Task wrapper in TaskOption.either input · New Use a task-wrapped option in TaskOption.either example · New Correct TaskValueOption.either callback and input types · New Use ValueNone in the ValueTaskValueOption example · New Correct JobResult.eitherMap XML documentation types · New Correct summary terminology and malformed parameter tag · New Document new Result requireWith helpers · New Correct TaskResult helper type in XML documentation · New
|
@TheAngryByrd FYI I have a solution for the Bind X With X Task/Async/Job explosion; will likely have something to push later... |
001350f to
176af72
Compare
|
@TheAngryByrd Took some time, and it's a monster, but despite the churn it'll cause I believe it's for the best... I've tried to explain it relatively simply in the PR overview (and/or the effects on the docs and README make the pattern clear) It may make sense to offer a way to make the |
bca88cf to
de9bcb9
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Compile-breaking module shadowing and critical requirement-binding and lazy-error regressions remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 5
Open (34)
Avoid CancellableTask module shadowing · New Avoid CancellableValueTask module name collision · New Bind CancellableValueTaskResult.req over Ok values · New Avoid ValueTask module name collision · New Use Req.noneWith in bindRequireNoneWith · New Constrain bindResult to Result-returning binders · New Add missing JobResult require With APIs · New Correct Async requireTrueWith migration diagnostics · New Make Req.deferError private · New Correct Req.isTrueWith migration diagnostic · New Correct Task requireTrueWith migration diagnostics · New Correct lazy wrapper migration guidance · New Correct Async.req documentation to describe Async and Option unwrapping · New Correct AsyncResult error text · New Use CancellableTaskOption.none instead of nonexistent non · New Remove unmatched closing brace from F# example · New Document CancellableTaskResult.req and reqExists · New Correct CancellableValueTaskOption.either callback types · New Correct JobResult Req.empty sequence description · New Return Job<Result> from tryParseIntJob · New
And 14 more that still need to be addressed.
Resolved since last review (10)
Qualify runTestsInAssemblyWithCLIArgs with Tests Correct TaskResult helper type in XML documentation Correct summary terminology and malformed parameter tag Correct JobResult.eitherMap XML documentation types Use ValueNone in the ValueTaskValueOption example Correct TaskValueOption.either callback and input types Use a task-wrapped option in TaskOption.either example Document the Task wrapper in TaskOption.either input Correct CancellableValueTaskOption.either signature Document the CancellableTask option input wrapper
| /// </summary> | ||
| let backgroundCancellableTaskResult = BackgroundCancellableTaskResultBuilder() | ||
|
|
||
| module CancellableTask = |
| let backgroundCancellableValueTaskResult = | ||
| BackgroundCancellableValueTaskResultBuilder() | ||
|
|
||
| module CancellableValueTask = |
| open IcedTasks | ||
|
|
||
| [<RequireQualifiedAccess>] | ||
| module ValueTask = |
|
@TheAngryByrd remaining work / considerations:
I'm definitely ready to get my life back from this rabbit hole though; I can imagine the review burden/desire to tell me where to go must be strong? If you can give me a steer on whether you think this can fly and/or the degree of to/fro you feel might be needed, I'll do some dogfooding internally to validate? |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
One or more issues must be addressed before approval.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 4
Open (10)
Use JobResult.ok for JobResultOption.none · New Avoid ValueTask module name collision Avoid CancellableValueTask module name collision Avoid CancellableTask module shadowing Fix misspelled equalWith helper name · New Correct Req.notEmpty cancellable result · New Remove extra delimiter from Result signature · New Remove extra delimiter from either signature · New Document Async parameter instead of Task · New Point ResultOption.singleton migration to ResultOption.some · New
Resolved since last review (31)
Use Req.noneWith in bindRequireNoneWith Bind CancellableValueTaskResult.req over Ok values Correct lazy wrapper migration guidance Correct Task requireTrueWith migration diagnostics Correct Req.isTrueWith migration diagnostic Make Req.deferError private Correct Async requireTrueWith migration diagnostics Add missing JobResult require With APIs Constrain bindResult to Result-returning binders Remove stray slash after param tag Remove stray slash after param tag Fix broken Req documentation links Remove stray slash after param tag Remove stray slash after param tag Remove stray slash after param tag Remove stray slash after param tag Use lowercase ValueTaskValueOption.none helper Use lowercase ValueTaskValueOption.some helper Correct onNone type to include unit argument Replace remaining TaskValueOption.valueSome call
And 11 more resolved.



Cleanups to harmonize AsyncResult, Result, TaskResult, CancellableTaskResult and JobResult:
ok(missing fromJobResult)ignore(missing fromAsync)bindResultgeneric helper for *Resulteither(erroneously namedfoldResult) onTaskResult,AsycResult,JobResulteitherMapto *Resultignore, addingRequireExplicitTypeArguments(more error-safe; aligns with FSharp.Core Task, Async, ValueTask) for Task, Async, Option*Option: makeeitherfollow equivalents in taking synchronous functions onlyvalueOr(was only present onResult; duplicates built-indefaultWith)Result.requireXand the asociated per-ComputationrequireXandbindRequireXto a singlereqfunctionReqfunction you write plugs into any container without any specific workReqfunctions have reliable and correctWithvariants as a one-linerreqfunction binding to anyReqfunction is present on all compurations and computation-results, soCancellableTask,CancellableTaskResult,CancellableValueTaskand many more gain the same support that only the baseline Async/Task/Job computations had to dateFixes:
FSharp.Corev 6.0.4 (for pre-net9.0builds)See changelog for authoritative list of changes
resolves #375