3 ms·
> It actually has a much better type system, in my opinion. I don't know how anyone can say that with a straight face about a type system that has both Option
by __s 6y ago
> It actually has a much better type system, in my opinion.
I don't know how anyone can say that with a straight face about a type system that has both Option & null
(granted Rust technically runs into this, but they go out of their way so that you should never be using pointers unless you want to. Whereas in F# you'll run into this using references, & you'd expect interfacing to C# APIs wouldn't take the care that interfacing with C APIs does)
That said, F# does sound like a good fit for them, so one funny reasoning aside, dive in. I enjoyed F# when I was able to use it
- gameswithgo 6y agoThere are like a thousand little details a type system has, and you focus on one thing, the existence of null for .NET interop, and decide this means the type system can't be overall better?
- McWobbleston 6y agoThe null thing is a bad example, particularly because it's from the .NET side and C# is focusing on removing that now through nullable reference types, but I'm honestly surprised they claimed F# has a better type system. F# lacks functors, first class modules, row polymorphism, GADTs, PPX extensions, and likely some others I'm not aware of. GADTs, row polymorphism, and PPX extensions I've wished for in particular because they solve some problems I frequently run into with MVU/Elmish architecture on the front end. F# instead has inline functions with static constraints (similar to C++ templates), type providers, computation expressions, and units of measure.
- zzbzq 6y agoI worked on some Scala codebases, which has this problem. It even lets you end up with Some(null). I call it the two billion dollar mistake.
- yawaramin 6y agoWas this because the devs didn't know about Option.apply?
- ojnabieoot 6y agoI have been using F# for 5 years and have never once needed to use “null” anywhere in my code - if I were to interact with a C# library I think null-handling is an acceptable price to pay for the interop (similar to weirdness with OCaml/Haskell and C FFI). F# makes that particular separation of concerns very clean and easy to handle. Idiomatic F# is safe against null reference exceptions. I think you’re needling a small wart in F# due to the .NET requirement, it’s hardly enough to say that F#’s type system is overall bad.
- StreamBright 6y ago>> I think null-handling is an acceptable price to pay for the interop Especially given how easy it is to deal with it. Option.ofObj what we use most of the time.
- phillipcarter 6y ago> Whereas in F# you'll run into this using references It depends :) F#-defined reference types cannot be assigned a null value by default. If your reference is an F# library (or one with F# bindings, of which there are several) then this isn't something you run into. Technically this can be bypassed by giving the type an attribute called AllowNullLiteral, but it is extremely rare to see that in practice because it's so unsatisfactory to use null from a cultural perspective in F#. Once a C# programmer uses F#, something switches on in their brain and they tend to eliminate all possible ways null can creep in as thoroughly as possible. It's neat. Another aspect where you don't see null is in initialization soundness. In F#, all values must be initialized before use. This is in sharp contrast to C# or Java where you can accidentally access something that hasn't been initialized before. While you can also technically bypass this to inject a null somewhere, it is also exceedingly rare because it's not a default behavior. F# data types also cannot be assigned a null value, so that's also a place where null doesn't come in. So it really leaves interop with .NET assemblies, some serialization scenarios, and .NET reflection. The first is really the only time people can still get "surprised" by a _null_ value. The rest are all technically possible, but just tend not to come up. The reason why this all matters is it's not a binary thing about having null/non-null. Just like it's not a binary thing about having exceptions/vs. not. It's about how frequently they can come about in normal programming scenarios. I can write a simple Haskell program that throws an exception at runtime, does that mean that Haskell is not safe? Of course not, because it's not usually what normal Haskell code does. The same thinking applies here. The ways that null can creep into an F# program are simply smaller than C# or Java and do create this mindset that nullis something that F# programmers tend not to think about that much.