| There are a couple of concepts in F# that I really like: * actor-based approach to concurrency[1]. Very useful when you want to design your code lock-free. Treating instances as agents that read messages from a mailbox, frees the developer from using low-level threading primitives. First time I've used this approach in production with AKKA and Scala. In F# it is much cleaner because the language itself is built on a better platform. * exhaustive pattern matching[2]. Writing in F# means using pattern matching a lot. Exhaustive matching gives you the confidence to refactor and maintain your code. The compiler will warn you when adding a new value in your type and not covering the execution path that uses it. It catches a lot of errors before you even push the changes to CI. * obviously immutability, conciseness, currying, these have been mentioned so far by others. One nitpick in F# are Exceptions [3]. They approached it similarly to how it is done in C#. You are allowed to define and throw an exception that will "jump" somewhere in the execution path.
I prefer when a method returns Option-style types. This way, you know what to expect from a call, and pattern matches on the result without adding one more execution path in your code, which covers exceptions separately. It was added to support C# style error handling, though I very much prefer an error-code-based approach. [1] https://fsharpforfunandprofit.com/posts/concurrency-actor-mo... [2] https://fsharpforfunandprofit.com/posts/correctness-exhausti... [3] https://fsharpforfunandprofit.com/posts/exceptions/ |