DEV Community

Discussion on: What's a useful programming language feature or concept that a lot of languages don't have?

Collapse
 
kspeakman profile image
Kasey Speakman • Edited

Two things I think are really powerful in F# that are not found in most languages.

Union types are a way to represent one of multiple different possibilities. It is a bit like an enum type that can have extra data with it.

type Payment =
    | ChargeCard of issuer:string * pmtToken:string
    | Check of checkNumber:int
    | Cash

let payment = Check 12345

Most languages have a way you can kinda-sorta define these. One common method in OO is an abstract base class with shallow inheritance. But it is a lot of code overhead versus the concise definition above. And it is also not particularly idiomatic to OO. People probably wouldn't bat an eye at using case on an enum, but type checking for a derived class is often considered a code smell.

You can also represent these choices as nullable fields in a single class, but then you have to write a bit of code to control access and protect against the case where none or multiple of them are set at once. Doable, but annoying enough that people usually don't.

Value equality by default is very nice for testing. It means I can do things like this:

type SomeType = {
    FooInt : int
    BarString : string
}

let expected = { FooInt = 1; BarString = "One" }
...
let actual = runSomeFunction input
actual = expected

If the actual has the same values as expected (1 and "One" here), then it will return true. And it works for union types too. In most languages, these things have reference equality by default. So the last line would only return true if actual and expected were pointing to the same memory location, which is not super helpful. You can usually get value equality in any language, but it might be a pain. In C# for example, you can override the default implementations of GetHashCode and Equals to get value equality. It adds an extra 8+ lines of code to every class definition (and each field adds more lines of code potentially). I believe a lot of people use tools to add them in automatically and then code folding to hide them. Or just manually check for equality when needed.

And I could go on: no nulls, immutability by default, pattern matching, composable asyncs, sequences, etc. Then I need to go fix something in our VB code base, and it's 😬😬😬. Well, one thing VB has that most others don't is XML literals. So there's that.

Collapse
 
jvanbruegge profile image
Jan van Brügge

I don't like when languages call abstract data types "union". Because it is technically not true. They are disjoint unions, which makes them nice to use. The only language that I know that has actual union types is typescript.

Collapse
 
kspeakman profile image
Kasey Speakman • Edited

F# calls them discriminated unions, technically. For the purposes of my comment I called them union types to keep it conceptually simple. The extra adjective "disjoint" or "discriminated" is more technically correct, but for many people it automatically biases them to react with "too complex; didn't read". When really it is a simple concept.