Top
Best
New

Posted by bozhidar 4/1/2025

Why F#?(batsov.com)
447 points | 413 commentspage 4
gwbas1c 4/1/2025|
If you've had C# and F# co-exist in the same codebase, how do they co-exist? Is it like C# and VB.Net where a project (dll) is either C# or VB.Net, and they can reference each other?

Or: Is it more like the Swift / Objective C ecosystem where Swift, Objective C, and even straight C can co-exist in the same library?

In a mixed C# and F# codebase, generally when do you favor C# versus F#?

Coming from a C# background, what are the areas where F# is a better language?

Any success stories for F#, especially if it co-exists with C#? Any horror stories?

neonsunset 4/1/2025||
You have likely heard "functional core, imperative shell". This refers to having IO-heavy code that favors imperative patterns be written in C# and then have the actual domain logic core written in F# which is much better at expressing it. Because both languages are hosted on .NET, you simply achieve it by having two projects and having one reference another. It is very seamless F# and C# types are visible to each other if marked to be so.

The biggest advantage of F# is its gradual typing and full type inference which allows to massively reduce the amount of text required to describe application or domain logic. It is also extremely composable and I find doing async in F# somewhat nicer than in C# too. F# also has better nullability (or, rather, lack of thereof) assurances and, in my opinion, better UX for records.

gwbas1c 4/1/2025||
That's just like how C# and VB.Net can co-exist in the same project. Would you pick the pattern of:

1: C# Library with interfaces and/or abstract base classes

2: F# library with implementations of those interfaces and base classes

3: C# program (console, web service, GUI, ect) that specifies the implementations in Dependency Injection

Or is there a simpler way for C# and F# to co-exist in the same project (dll or exe)?

int_19h 4/1/2025||
You don't really need to split 1 & 2, since F# can define .NET interfaces and abstract classes just fine.

For that matter, you don't even need the interfaces if you wouldn't have had them in a C#-only solution. Just define the class in F# and use it directly from C#.

You still need a separate assembly for F#, but that doesn't imply dependency injection - again, just reference it and use it.

gwbas1c 4/1/2025||
I've identified a possible use case for F# in a preexisting product; I'm looking for the simplest way to integrate F#.
Lanayx 4/1/2025||
F# excels in writing domain logic where main domain entities are defined as records and discriminated unions and logic is written in pure functions. Given that product is preexisting and domain entities must already be defined, I wonder what use case do you have in mind?
gwbas1c 4/2/2025||
Realtime control logic for infrastructure.

The basic decision making logic needs to be very simple and easy to follow by scientists and people who aren't day-to-day software engineers: Basically, input some data, such as sensor readings, run it through an algorithm that makes decisions, and then output the decisions.

debugnik 4/1/2025||
Yes mixing is just like with VB.NET.

When mixing, you often write business logic as self-contained F# libraries with a C#-friendly API; and use C# to integrate them with whatever imperative, reflection-heavy and DI-heavy frameworks .NET is promoting the current year, since those are filled with interop edge cases for F# anyway.

You really want to avoid a language sandwich though (e.g. C#/F#/C#), because you'll keep wishing to remove the middle layer. Sadly, the addition of source generators make this mistake even more appealing.

loxs 4/1/2025||
I tried F# some years back when I was searching for a language to port my OCaml project in... It felt too much .NET-y and too much MicroSoft-y. And back then .net for linux had just been released and was somewhat unpolished.

It seemed that I had to learn C# in order to use F# properly and it seemed that porting it to C# was the saner option. I went with Rust after all and it seems to have been the right choice.

iLemming 4/2/2025||
> felt too much .NET-y and too much MicroSoft-y

That was kind of my main problem with dotnet stack in general, although that was some years ago. I've tried sneaking F# into our project by building set of tests (the main codebase was in C#), but some of my teammates would have none of that.

My personal perception of the dotnet community was that developers either were too pigheaded about doing things "the Microsoft way", or hyped about "innovation" — "Oooh... check this out, Scott Hanselman made a whole new conference talk about it...", and then you'd look into this "innovation", and it often turns out to be some decades old, well-known thing, only "wrapped into MSFT packaging", which is not really bad by itself - it just seemed that people didn't actually use them in a practical way. I just never found that sweet-spot between pragmatism and excitement. You have to find a middle ground between: "This works! Sure, yeah, but isn't it darn ugly and probably not scalable?" and "This is so beautiful, and cool, but nobody besides Jeff really understands it." And my personal experience was that .net programmers would always want to be on one of those sides.

airstrike 4/1/2025||
This rings true to me as well. I'm not sure what I get out of F# that I can't get from Rust, unless you specifically want .NET, which I don't.
DeathArrow 4/2/2025|||
You get speed of development, productivity, lots of libraries. You get something that is easy to learn and understand.
airstrike 4/2/2025||
Lots of libraries if you want .NET, right? But if you don't, Rust has way more libraries

Speed of development is debatable. I think you can be pretty fast with both.

Easy to learn I concede but it gets easier with time, until it becomes very easy

loxs 4/5/2025||
Having written a moderately big project in OCaml which I tried porting to F# and later did port to Rust, to me Rust feels much faster to develop than either OCaml or F#, especially once you figure out the "core", adding more features is a breeze. Refactoring is also easier. Not to mention that reading Rust is much easier than reading OCaml and coming back to the project after a year feels very easy. I think that I have less bugs with Rust than with OCaml. And the end product's core ended up being ~3-4 times faster to execute in Rust.
UK-Al05 4/2/2025|||
Less arduous memory management.
airstrike 4/2/2025||
I am not sure what you mean. My memory management for a recent 30k LOC app boils down to "thinking before cloning"
RKFADU_UOFCCLEL 4/1/2025||
F# is a very well-polished functional language. Think of it to Haskell as C# is to Java. No worries about space leaks or purely-academic syntax or monads (though you can get those if you need them). All with tight integration into one of the biggest, well-established ecosystem (CLI). It's managed by smart people who know how to keep it from derailing as it grows.
froggertoaster 4/1/2025||
Coming from a .NET developer - why NOT F#?

* Network effect, or lack thereof. Very few people use it. * Its nature is contrary to the ecosystem. The CLR is fundamentally resistant to the paradigms that F# creates.

Wonderful little language - one of my favorites - and we owe a lot to it for the great features that C# has. But it just hasn't picked up the critical mass it needs.

DeathArrow 4/2/2025||
F# is a lovable language as in people are really enjoying using it vs not being bothered using it.

Once every other month a new F# link lands on top page and receives a few hundred of upvotes.

I think F# needs and deserves more publicity in order for it to win a larger audience. If only F# community would be half as vocal as Rust community.

ClimaxGravely 4/3/2025||
I work in an industry where F# is a non-starter but I still love to use it outside of work. Also what I learn from F# and functional programming still benefits me in my day job (mostly c++). I think I tend to write a bit safer code after understanding the benefits of a functional language.
twodave 4/1/2025||
In the case of F#, the use cases are diminishing with every new C# release, since C# is getting better and better at the things F# is supposed to be strong at (record types, pattern-matching, etc.). Better to write the thing in C# using modern features of the more popular and capable language.
throw234234234 4/2/2025||
Not sure that C# is the more capable language - its still that F# is mostly a superset of C# although C# is catching up. I think they are on par w.r.t capability (i.e. CLR compatible). In terms of conciseness, and expression F# still wins IMO; and given some of the extra features can be more performant at times (e.g code templating/inlining vs just JIT attributes). Custom CE's (Async/TaskSeq), nested recursive seq's great for algorithm dev, DU's, etc. There's a lot of little features C# doesn't have (or don't quite fit) that when I write C# I'm forced to implement still more cruft code around.

IMO its generally more readable as well to non-dev than C# and to dev's outside the Java/C# ecosystem (e.g. Node, Go, etc). I've shown F# code back in the day to non-tech stakeholders and they typically understand it (e.g. data modelling).

arwhatever 4/1/2025|||
Unions remain the killer F# feature missing from C#.

Also, basic object initialization in C# has turned into a nightmare with recent versions. You need a flowchart to select among the 18 syntax options which suite your current needs.

With F# (and other newer languages), record fields are either `T` or `T option`. No need to worry about whether the value needs to be computed in a constructor and then remain immutable, whether it needs to be initialized by an object initializer and/or a constructor or not, whether it needs to remain interior-ly mutable throughout the life of the record, and so on. (Although as I recall you do still need to consider null values assigned to non-nullable references in your F# code that consumes C#.)

twodave 4/2/2025||
There's a draft spec out there for discrete unions in C# fwiw. I wouldn't be surprised to see it in another version or two.

And while I agree that I don't love some of the object initialization patterns C# allows--I respect that other people might have different style than me and don't mind ignoring that those styles exist when writing my own stuff :)

My general rule goes something like:

1. Use record types for any simple data structure

2. Avoid using primary constructors (even on record types).

3. Use { get; init; } properties for everything unless there's a good reason not to.

4. For things that need to carry internal state, have different methods for mutations, emit events, etc., use a class with regular old constructors and either { get; } (for immutable) or { get; private set; } (mutable) properties as needed.

DeathArrow 4/2/2025|||
F# can be nicer to use for a functional programming style.

It's not always about the features such as keywords, built-in functionality and types. It's also how language features work together.

C# is more fit for an imperative or OOP style when F# is more fit for a functional style.

marcosdumay 4/1/2025||
You may start to get a point when C# gets a two-directional type inference system. As it's now, any functional-looking code requires so much boiler plate that it's shorter and less bug-prone to copy your functions code everywhere you want to use them.
int_19h 4/1/2025||
Can you give an example of said boiler plate?
DeathArrow 4/2/2025|||
Using OneOf library or something similar instead of discriminated unions / sum types.

Trying to use a functional pipeline instead of DI.

marcosdumay 4/2/2025|||
Just try to make any generic high order function in C#. Any one you can think of.
amelius 4/1/2025||
I have a few questions. Can it do GUIs well? How about mobile? And how does it compare to e.g. Scala?
dagw 4/1/2025||
Can it do GUIs well?

I don't know if I would say 'well'. For simple GUIs it's OK but, for non-trivial GUIs I would use the approach to write the GUI frontend code in C# and have it call the F# 'backend'. If for no other reason than that the support and documentation for doing GUIs in C# is much better.

How about mobile?

Never tried, but I'm guessing more or less the same story as above. I would probably start by looking into .Net MAUI for that.

And how does it compare to e.g. Scala?

The biggest difference is that Scala is a much bigger and more of a multi-paradigm language. F# feels smaller and more focused and on its ML roots and functional programming. Not saying that Scala is less 'functional' than F#, but Scala supports you writing your code in a much more OOP way if you want. Yes you can (and sometimes have to) do OOP in F#, but it doesn't feel natural.

pjc50 4/1/2025|||
Because it's a CLR language, it has access to all the same technologies as C#. That is, all the Microsoft native ones plus cross-platform with Avalonia.

https://fsharp.org/use/desktop-apps/

Lanayx 4/1/2025|||
For web UI we have Fable and it's integration with well-known js frameworks, also WebSharper (although it's less well-known) and Bolero (on top of Blazor)

For mobile we have FuncUI (on top of Avalonia) and Fabulous (on top of Avalonia, Xamarin and Maui). Most of these frameworks use Elm architecture, but some do not. For example I use Oxpecker.Solid which has reactive architecture.

Can't help with Scala comparison, but at least DeepSeek V3 prefers F# for UI https://whatisbetter.ai/result/F%23-vs-Scala-9eaede00c7e4485...

ivm 4/1/2025|||
.NET for iOS and Android is very robust, I’ve been developing with it since 2018. Just avoid using MAUI for interfaces because it's still quite unfinished after the rewrite from Xamarin.Forms.
munchler 4/1/2025|||
It can do GUIs well, although it takes some finesse to manage user state in an immutable-first language. Check out Fable for building web apps: https://fable.io/

I don't have much experience with Scala, but I think the two languages are pretty comparable in their respective ecosystems. The biggest difference I'm aware of is that Scala has typeclasses and F# does not.

int_19h 4/1/2025||
F# is not really that strong on immutability, though. Sure, variables and struct fields are immutable by default, but making them mutable is one keyword away. Similarly with classes - declaring readonly properties is more concise, but when you need a read/write one, it's readily available.
jcmontx 4/1/2025||
Sprinkle some HTMX next to your favorite template engine and you're g2g
Akronymus 4/1/2025||
Which is what I am doing with my personal website for the most part. Elmish for the subpages where a lot of interactivity is actually needed. Otherwise just using Feliz.ViewEngine with htmx purely for enhancements
gwbas1c 4/1/2025||
> 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!

kowalgta 4/1/2025||
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.

Foofoobar12345 4/1/2025|||
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.

arwhatever 4/1/2025||
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.

DeathArrow 4/2/2025||
Also C#:

bar = foo switch

{

   true => 7,

   false => 11

}
arwhatever 4/2/2025||
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.

malakai521 4/1/2025||
A nicer, cleaner and simpler syntax, superior pattern matching, active patterns, discriminated unions and computation expressions
int_19h 4/1/2025||
C# has the equivalent of active patterns these days.
malakai521 4/1/2025||
It does not
fud101 4/1/2025|
I want to ask a weird question. I'd love to learn ASP.net but i can't bring myself to deal with Microsoft Windows and their tech. Is F# a way for me to learn enough NET to make some money?
jcmontx 4/1/2025||
I'm .NET dev and haven't touch a windows device since 2019. Work on Mac, deploy to Linux.
CharlieDigital 4/1/2025|||
I am also a C# dev and haven't worked on a Windows machine in 5 years.

C# and F# both work fine with Rider or VS Code on Mac or Linux.

lunarlull 4/1/2025||
> i can't bring myself to deal with Microsoft Windows and their tech

Even in a VM? Why not?

More comments...