Comments (12)
For a more concrete example, you can an async CE inline and do something like this:
let doTheThing () = asyncResult {
let! user = async {
let! myResult = tryGetUser(1)
match myResult with
| Ok user -> user
| Error msg -> //custom errorHandling
}
}
from fstoolkit.errorhandling.
Would you consider adding this helper function to the AsyncResult module?
module AsyncResult =
/// Awaits a result type without resolving it.
let awaitResult (f: Async<Result<_, _>>) =
f |> Async.map Ok
// Usage
// tryGetUser = int -> Async<Result<User, string>>
let! myResult = tryGetUser(1) |> AsyncResult.awaitResult // returns a Result<User, string>
match myResult with
| Ok user -> printfn "User: %A" user
| Error err -> printfn "Error: %s" err
from fstoolkit.errorhandling.
Yeah this is a known problem with how the binding overloads work in F#. 😞 This is discussed in #88
Short answer, use the async
CE instead of asyncResult
or rework so you don't need to do this.
from fstoolkit.errorhandling.
Shoot.
So then my options are to revert back to Cvdm version, or rework with async CE.
I suppose async CE is the better choice since Cvdm is no longer maintained.
from fstoolkit.errorhandling.
Yeah I did this in my codebase in many places as well. I should probably find the F# RFC for helping fix this issue so people 👍 it.
from fstoolkit.errorhandling.
:.(
from fstoolkit.errorhandling.
I'm glad you found a solution that works for you but I don't think I would accept it. Here are some of my reasons:
- I'd like for the real fix to be in the F# compiler itself and I'm shy to add work arounds to the library for it.
- This creates a Result in a Result so
Async<Result<Result<'a,'err>,'err>>
which doesn't seem obviously useful. awaitResult
seems like a misnomer, it's not really awaiting anything, just nesting it.- Explaining why this is useful in a doc-comment can be very tricky.
from fstoolkit.errorhandling.
I believe fsharp/fslang-suggestions#905 is the correct suggestion to fix this in the F# compiler. I think I need to add to that issue since our particular case is because use the Source
transformation to help cut down on the need for combinatorially explosive extension methods (reduction shown in #83).
from fstoolkit.errorhandling.
- It's meant to be more of a shim / adapter, so it's not the same 'err in the outer result.
It would be more like this: Async<Result<Result<'a, 'originalError>, 'adaptedError>>
So the use case being that you are using a custom error DU within your asyncAwait CE, and then you want to await an async result function that doesn't use your custom error DU, and you don't want to unwrap the result.
- The name could be better. (I was loosely thinking of Async.AwaitTask which wraps a task)
- Yes, it is somewhat of an edge case -- although it didn't take very long for this case to come up for me.
I hope you'll change your mind. But if not, I guess it's an easy enough function to create locally.
from fstoolkit.errorhandling.
Looking again at #88, I think this is slightly different.
I'm not getting the "lookup of indeterminate object type" error.
The issue is that I'm using a custom error DU in my awaitResult -- in my case, DrawingLogError
-- and I'm trying to await a function that returns a result with a different error type: ProjectData.getBim360ProjectInfo // Async<Result<ProjectInfo, string>>
.
// Custom error DU
type DrawingLogError =
| ForgeNeedsAuthorization
| GeneralError of string
asyncResult {
let! token = AuthController.tryGetBim360Token3 ctx |> Result.requireSome ForgeNeedsAuthorization
// has return type of Async<Result<ProjectInfo, string>>
// I want to await Result<ProjectInfo, string> without unwrapping the result.
// fails with "Type mismatch. Expecting a Async<Result<ProjectInfo, DrawingLogError>> but given a Async<Result<ProjectInfo, string>>".
let! bim360ProjectInfo = ProjectData.getBim360ProjecInfo dbCtx projectId
match bim360ProjectInfo with
| Ok projInfo -> // do stuff
| Error msg -> // do alternate stuff
}
So the shim function wraps the Async<Result<ProjectInfo, string>>
within the matching error type Async<Result<Result<ProjectInfo, string>, DrawingLogError>>
.
(Which is a very ugly type signature that should never be gazed upon with human eyes!)
from fstoolkit.errorhandling.
Also stumbled on this recently and thought of a potential solution. Please excuse the names, they are just placeholders!
// Marker DU, not used directly
type AsyncResultBindAsResult<'T, 'TError> = AsyncResultBindAsResult of Async<Result<'T, 'TError>>
// Wrapper function
module AsyncResult =
let bindAsResult (x : Async<Result<'T, 'TError>>) =
AsyncResultBindAsResult x
// Overload added to AsyncResultCE
member inline __.Bind
(
bindAsResult: AsyncResultBindAsResult<'T, 'TError>,
binder: Result<'T, 'TError> -> Async<Result<'U, 'UError>>
) : Async<Result<'U, 'UError>> =
async {
let (AsyncResultBindAsResult asyncResult) = bindAsResult
let! result = asyncResult
return! binder result
}
// Usage
// tryGetUser = int -> Async<Result<User, string>>
let! myResult = tryGetUser(1) |> AsyncResult.bindAsResult // returns a Result<User, string>
Not actually tested so there may be some hurdles I'm missing.
Although advantages are pretty slight over the "double-result" solution above.
from fstoolkit.errorhandling.
AsyncResult
How would I go about defining this ? I get an error in Rider for the member: Unexpected Member in definition.
Sorry if the question is weird, Im still new to F#
Or is there a better fix available by now?
from fstoolkit.errorhandling.
Related Issues (20)
- Task wrapped result + option helpers HOT 1
- Worried about the Diamond dependency problem HOT 6
- Documentation for Validation operators mentions Bind (>>=), but the library doesn't implement it HOT 1
- Should List.sequenceValidationA preserve order? HOT 2
- FSharp.Core version warning (net7.0) HOT 14
- Make Result.defaultWith accept error, or remove it HOT 2
- Overload issues with TaskResult on generic functions HOT 2
- Add Option.ofPair HOT 5
- Add asyncValidation CE, or make asyncResult (and result?) CEs work with 'and!' HOT 4
- Can we reinstate `TaskResult.foldResult` and the like? HOT 4
- Add Light/Dark Theme Toggle to Gitbook Docs
- Support ValueOption in FsToolkit.Errorhandling.asyncOption HOT 3
- Support TaskValidation to match AsyncValidation HOT 2
- Binding Async<'T option * 'T option> to AsyncValidation is having overload errors HOT 1
- Common Language Runtime detected an invalid program HOT 2
- TaskOption/TaskResult defaultValue and defaultWith
- Support requireValueSome and requireValueNone in Result, TaskResult and AsyncResult
- Async/Job/Task wrapped result + require functions helpers
- feat(Seq): Add sequenceResultA HOT 6
- Readme video unavailable HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fstoolkit.errorhandling.