>=1.3.0 breaks type inference of unwrapped types
See original GitHub issueThanks again for fixing #86. After updating to 1.4.1, however, I still get errors from code which compiled with 1.2.6.
Here’s a minimal repro:
type X() =
member _.A = 1
let f () = asyncResult {
let! v = async { return X() }
return v.A
}
Under 1.2.6, this compiles. Under 1.4.1, the compiler can’t figure out the type of v' and errors out with a “lookup of indeterminate object type” on v'.A
Note that if you replace X() with a record, the code may compile because F# will infer types from members of records, but not from members of classes and anonymous records.
Possible workaround: unwrap v inside a regular async CE instead:
let f () = asyncResult {
let v = async { return X() }
return! async { let! v' = v in return v'.A }
}
I’ll still need to roll back to 1.2.6 though because we have this pattern every single time we make a database query:
asyncResult {
use cmd = Db.Query(connStr)
let! records = cmd.AsyncExecute(args)
// do stuff with records
}
Issue Analytics
- State:
- Created 3 years ago
- Comments:17
Top Results From Across the Web
Force binding on top wrapper · Issue #86
Just found this broke some of our code after running a test paket update . ... >=1.3.0 breaks type inference of unwrapped types...
Read more >Implicitly Unwrapped Optionals in Swift
An implicitly unwrapped optional is similar to a regular optional, but is automatically unwrapped when accessed. This means that you can access the...
Read more >typescript: generic constraints cause type inference to pick ...
I'm trying to constrain the Set builder to accept only types for which equality is properly defined (to avoid this problem). strange.d.ts
Read more >Type Checking and Inference for Dynamic Languages
Type inference is a generalization of type checking that automatically infers types while performing checking. However, stan- dard type inference often ...
Read more >CHANGELOG.md
Breaking Change #50383: Report a compile-time error for all cyclic dependencies during top-level type inference. Previously, some of these dependencies were ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

I too vote 2. As I mentioned, we use this type inference every single time we make a database query, and we cannot add a type annotation because the type is generated by the type provider and doesn’t have a usable name.
On the other side, the issue #86 (that the
Bindin #87 resolved) only appears in a couple of spots through our codebase, and a workaround should be possible, since all CEs are just sugar, although it seems a bit tricky.For reference, take this piece of v1.2.6 code:
Not sure how this could be done in v1.4.0 without forsaking the use of
asyncResultentirely.@TheAngryByrd the issue happened when we had a long
taskResultcomputation, as usually every API endpoint is a singletaskResultCE, but at one particular point in the flow we had an error return that we were able to handle on the spot instead of returning a HTTP failure. Restructuring the entire CE to be a plainasyncwith manual error handling would not be worth it.For now, I’ve solved it somewhat clumsily by running the right side of the unwrapping throgh
Task.map (function | Ok x -> Choice1Of2 x | Error y -> Choice2Of2 y), so theChoicedoesn’t get unwrapped and it can be handled manually.