|
> So what you'll have to do is tell your teammates to not use nulls, and instead make proper use of option etc, and then you're back to avoiding NREs by conventions, not by the compiler helping you out. Am I incorrect in this? You're not wrong, but I think you're being too rigid. Type safety isn't a yes or no, it's a sliding scale between mathematically-guaranteed correctness at compile time and unsafe user convention, and on that scale F# is definitely to the left of C# - although it's to the right of Haskell and dependently-typed langs - because while it doesn't provide full safety, it still make safe code easier to write (the famous "pit of success"). Sure, F# lets you write "null" instead of "None" if you want. But C# lets you write, e.g., "dynamic" - does that mean C# lacks static typing and "avoids MissingMemberExceptions by convention"? Of course not; you have to go out of your way to use dynamic, because the language provides you with static types and encourages you to use them. Likewise, F# provides you with the Option type and encourages you to use it - you have to go out of your way to use null in its stead. A F# coworker that used null would be committing an obvious code review faux pas, much like a C# coworker that insisted on using dynamic duck typing instead of interfaces. (Whereas "null" is generally not considered a code smell in C#... and note that it's entirely possible and not at all difficult to implement a safe Option type in C#! It's just neither idiomatic nor popular.) Another example is casting. In weaker languages, casting is implicit and dangerously uncontrollable. C# does better: you must explicitly cast types, but it's up to you to make sure it's a safe cast. And F# goes a tiny bit further: you have separate operators for safe upcasts and unsafe downcasts, and using the former on an unsafe cast won't compile. It's not 100% safety, but it's still better. |