3 ms·
Most incompatibilities can be summarized to "source generators" and tooling that relies on other forms of code generation. This can be fairly easily dealt with
by neonsunset 2y ago
Most incompatibilities can be summarized to "source generators" and tooling that relies on other forms of code generation. This can be fairly easily dealt with by writing a helper C# project with the necessary "glue".
Other than that, is there something specific you have in mind?
F# 9 even supports consuming ref struct generic arguments recently added to C# and plans to introduce their definition in F# itself AFAIK (which is likely going to be a nicer experience than in C#!). It has been doing impressively good job at keeping up thus far and deserves way more recognition for this.
- hansvm 2y agoOff the top of my head, async is monstrous to integrate between the two languages. Even when it works it's slow.
- neonsunset 2y agoThis was addressed in F# 6: https://learn.microsoft.com/en-us/dotnet/fsharp/whats-new/fsharp-6#task- https://learn.microsoft.com/en-us/dotnet/fsharp/whats-new/fs... Asynchronous sequences (IAsyncEnumerable) support is provided via https://github.com/fsprojects/FSharp.Control.TaskSeq https://github.com/fsprojects/FSharp.Control.TaskSeq F# is a very capable language - a broad spectrum of tasks can be solved by just implementing a new CE, something I could not even think of in C#.
- hansvm 2y agoKind of. It supports the C# Task interface nicely (and has for ages), but it you have a bunch of F# async code then you still have to marry the two somehow, and that's still monstrous.
- neonsunset 2y ago|> Async.AwaitTask ? Or is there a particular case that’s problematic? So far I have not seen any interoperability issues around this (even though yes, async CEs are way less efficient than task CEs) but I’m still learning so additional details would be appreciated.
- hansvm 2y agoThe two languages have two different async abstractions which at their core aren't compatible in general. When that happens in software, one of several possible options will happen. The thing Microsoft chose here is to give an API that looks like it's compatible but which is subtly broken for a nontrivial fraction of code (other common choices include rejecting any level of compatibility, providing more complicated APIs allowing the user to handle the multi-language nuances, or providing an incomplete API which works as expected). Much like how when one proposes a perpetual motion machine you know there must be a bug in the math somewhere, when somebody proposes an interop between two incompatible data structures there must also be a drawback. Pick literally any feature of the language other than sequentially executing code (exceptions and threads are usually great ways for languages and specs to fall apart), and you'll likely find places where the interop struggles. A few that come to mind: - That solution is only one direction. Interoperability needs to go both ways. - The exception interface between the two constructs is sufficiently poorly defined that I'd call it a footgun, and code that won't wake you up at night usually has to do extra work. - Performance in that kind of wrapping is a nightmare, both from the overhead of additional runtime layers, and, more importantly, because the last time I checked it was basically "sync over async" in a way that made the type system happy. - Going back to the exception thing, cancellation tokens are especially poorly handled in that interop one-liner. - They still haven't fixed blunders like ConfigureAwait(false), and the interop code absolutely has to care about that sort of thing in applicable contexts (the worst offenders being any sort of "main thread owns everything" code like current popular GUI paradigms).
- neonsunset 2y agoThis reads as an AI-generated text that is very emotional but provides few meaningful technical details (no examples, unrelated APIs, ConfigureAwait - really now?).
- hansvm 2y ago> AI-generated Be nice please. > Emotional I'm not sure if this makes me sound more or less artificial, but outside the use of the word "blunder" there were scarcely any strong opinions, much less emotions. > Few technical details You came across as having done enough F# and C# to not need a novel to understand. Yes, those APIs are related to the problem of merging tasks and async between the two languages. 95% of the time you won't care, and 5% you'll hit a footgun. Just go write some multilingual GUI async code with a few cancellation tokens and exceptions and report back with the edge cases you find. The two abstractions are sufficiently different that you will necessarily find some, and if you aren't fortunate enough for your F# codebase to be mostly Tasks instead of async the you'll have to actually care.
- phillipcarter 2y agoYou don't really. F# has the task{} abstraction that works just like C# and is fully compatible.
- hansvm 2y agoWhich works fine assuming all new development is happening in the F# half of a codebase and you don't have a significant amount of old F# async code lying around.
- phillipcarter 2y agoIt doesn't require that. You can do a strangler pattern of sorts and use task for the interop layer, then run each call site through a small helper that converts to F# async. Or, hell, just throw caution to the wind and text replace. I've heard some folks do that and it worked out well for them + wasn't much time to clean up either. They're especially happy to have better stack traces too.
- hansvm 2y agoSo...it _does_ require that, but if you have time/risk to spare then there exist tenable migration strategies.
- algorithmsRcool 2y agoThe F# team has done a great job of building compatibility bridges back to the C# way of doing things so the actual impact isn't bad.