←back to thread

Why F#?

(batsov.com)
445 points bozhidar | 9 comments | | HN request time: 1.056s | source | bottom
1. gwbas1c ◴[] No.43546618[source]

> Why F#?

I'm kinda wondering if anyone here with decent C#/.net experience can give their version of the answer?

---

The article really didn't answer its own question. It basically says "How" instead of "Why"...

...Which as someone who's spent over 20 years in C#, and tends to advocate for "functional" style, leaves me with more questions than answers!

replies(3): >>43547924 #>>43548267 #>>43548811 #
2. kowalgta ◴[] No.43547924[source]

I've worked with .net professionally for almost 20 years. At the beginning with C# while last decade almost exclusively with F#.

F# is just a better language. Simpler, more concise, more readable with stronger type safety. I will never go back to writing C# as I'm finding it too frustrating at times and unproductive.

3. malakai521 ◴[] No.43548267[source]

A nicer, cleaner and simpler syntax, superior pattern matching, active patterns, discriminated unions and computation expressions

replies(1): >>43549041 #
4. Foofoobar12345 ◴[] No.43548811[source]

Everything is an expression (i.e. its an actual functional programming language), and along with it comes a different way of thinking about problems. Coupled with a really good type system which has discriminated unions, you'll have much fewer bugs.

Pro tip: don't write F# like you would write C# - then you might as well write C#. Take the time to learn the functional primitives.

replies(1): >>43551372 #
5. int_19h ◴[] No.43549041[source]

C# has the equivalent of active patterns these days.

replies(1): >>43550425 #
6. malakai521 ◴[] No.43550425{3}[source]

It does not

7. arwhatever ◴[] No.43551372[source]

if I may elaborate on "everything is an expression," F# allows you to do things like (with apologies for being a tad rusty with the syntax)

  let bar = 
      if foo then  
         7  
      else  
         11

or

  let bar = 
      try
        // code that might throw
        7
      with ex ->
        11

and will ensure that both/all code branches return a compatible type for the `let` binding.

Whereas in C# you have to do like

  int bar;

  if (foo) {
     bar = 7;
  } else {
     bar = 11;
  }

And C# will let you know if you omit the `else` on accident ...

Except that most C# developers do

  int bar = 0; // or some other default value`

to get the red squiggly to go away while they type the rest of the code, unknowingly subverting the compiler's safety check.

This doesn't seem like a big deal given these examples. But it becomes a much bigger deal when the if/else grows super large, becomes nested, etc.

replies(1): >>43557515 #
8. DeathArrow ◴[] No.43557515{3}[source]

Also C#:

bar = foo switch

{

   true => 7,

   false => 11

}
replies(1): >>43558937 #
9. arwhatever ◴[] No.43558937{4}[source]

Ah yes that is definitely a nice addition to the C# language, albeit still with a couple of shortcomings compared to F#:

1. It doesn’t support code blocks, so if you need multiple lines or statements you have to define a function elsewhere. 2. To get exhaustiveness checking on int-backed enums you have to fiddle with compiler preprocessor directives.

And for #2 any data associated with each enum variant is left implied by C# and has to be inferred from a reading of the surrounding imperative code, whereas in F# the union data structure makes the relationship explicit, and verifiable by the compiler.