Lack of expressions is the main C# deficiency that will never get resolved. The other big advantage of F# is that it can be very easy to understand: file ordering means that you can read through from start to end to understand the code.
Ordinarily in a mixed codebase, the F# comes nearer the start, with C# depending on F#. That's because C# has lots of glue code to connect to the outside world (xaml, cshtml, EF...) and this is less straightforward to migrate to F#. The only problems with mixing languages is when you want F# in the middle of some project where it depends on some parts of the project and other parts of the project depend on it. But if you can identify something independent in a C# project and extract that out, you have already made the project simpler.
You can ignore async and use task. You can use async in the (very rare) cases when you don't want a hot task. You can also ignore Option and use ValueOption all the time. The struct types are new and have meant that F# does not have a performance deficit.
ValueOption is just better than Nullable<> since Nullable<> restricts to value types only. Resulting in Nullable composing terribly and requiring ad-hoc code everywhere.
You can choose which constructs you use. Avoiding classes in F#, while possible, would be a mistake as they are a way to hide data and functions where these are not intended to be part of the public API. F# is outstandingly pragmatic and the struct types for performance have been a nice addition. As a beginner you can ignore those if you are not interested in getting max perf.
Dotnet does have some minor annoyances (exceptions being one) but gives the ability to deploy everywhere, GUI apps on all platforms, web, backend is fantastic. Lack of native GUI apps would be the main deficiency for me from Gleam, plus the fact that they have decided their community is explicitly politically woke-liberal.
Rust has been a fantastic addition to the language ecosystem, but recursive types, which are the bread and butter of ML-family code, are just too hard to write in Rust.
Dotnet is ultra simple and a big advantage of F#. You do need to learn what a solution is: it's a group of projects with dependencies between the projects. Download an IDE, create a new project (which will also create a solution), and go to Nuget in the IDE if you need to install packages. You don't need to know what an assembly is.
Some devs like to do things the hard way with a very manual approach, including working with command lines and using paket, and that does give some confusions in the docs since there isn't a clear default path.
Oh, don't get me wrong, I definitely think dotnet is an advantage for F#, but when I learned F#, a lot of beginner resources didn't teach you how it dotnet works. I think it got easier from .NET Core 3 onwards tho.
A better formulation:
Abstractions do not adequately describe the full working of a system. So higher-level approaches will always require a knowledge of lower-level operations.
However, the opposing and terribly named "Dependency Inversion Principle" is true much more often: "High level [approaches] should not be dependent on low-level implementations."
Ordinarily in a mixed codebase, the F# comes nearer the start, with C# depending on F#. That's because C# has lots of glue code to connect to the outside world (xaml, cshtml, EF...) and this is less straightforward to migrate to F#. The only problems with mixing languages is when you want F# in the middle of some project where it depends on some parts of the project and other parts of the project depend on it. But if you can identify something independent in a C# project and extract that out, you have already made the project simpler.
You can ignore async and use task. You can use async in the (very rare) cases when you don't want a hot task. You can also ignore Option and use ValueOption all the time. The struct types are new and have meant that F# does not have a performance deficit.
ValueOption is just better than Nullable<> since Nullable<> restricts to value types only. Resulting in Nullable composing terribly and requiring ad-hoc code everywhere.