- NULL values still are a problem because they can be introduced any time you interact with the .NET framework. I got hit by this almost right at the beginning when first using the language – i defined some data type with non-optional fields and used it as an argument to an ASP.NET Core controller method only to realize that my non-optional fields don't enforce anything and ASP.NET will happily set them to NULL when data aren't present.
- There are multiple slightly different ways to define data types – classes, records, discriminated unions – and it's not immediately clear what are the consequences of using which. I remember having to switch some of my datatype definitions to classes because otherwise i couldn't make ASP.NET Core automatically deserialize them.
- You still have to learn in detail how all of the C# and .NET concepts map into F# to work with .NET and other libraries, e.g., there is a weird duplication of collection types, sometimes you have to do a weird casting dance with the :> and :?> operators when working with interfaces, dealing with out parameters also took me quite some time to figure out.
- Namespaces, classes and modules also seem to have some confusing redundancy.
I've tried out F# only once for a single project so a lot my complaints are probably due to my inexperience with the language, but all in all it seems that a lot of the suffering is inflicted by the association with .NET and the language could have been a lot nicer if it wasn't tied to it (I'm not dismissing the benefits of it, though).