Why F#? (batsov.com)
406 points by bozhidar a day ago
raphinou a day ago
F# was for me the best functional language when I looked at rewriting a Ruby on Rails app. I wanted to go with a functional language, as it seems to better fit my thinking and reasoning, and I looked at Haskell, Ocaml, Scala, F#.
Being a stranger to Microsoft technologies, F# was the least likely to be chosen, but easily became the first choice. Haskell's purity made it hard to adopt (for me), Ocaml's ecosystem is subpar (there wasn't even a clear choice for a library to interact with postgresql, I couldn't install the latest version due to its reliance on an obscure tool whose name I forgot and didn't get help on the forum), and Scala is seems complex....
F# was surprisingly easy to get started with. The community is mis-managed by a corporate-minded approach (requiring people to become member of the F# software foundation to get access to the official slack!), but its members are friendly, smart and ready to help. The ecosystem is great with access to all the dotnet libraries (some complain there's a mismatch as most of those are developed for use with C#, but I rarely got in trouble for using them).
There are also great libs and frameworks available. Like https://github.com/SchlenkR/FsHttp to easily interact with http servers, to the point that I find it easier to use than a dedicated library. Or https://github.com/CaptnCodr/Fli , to run commands. And last but not least, https://www.websharper.com/ is the best web framework I have encountered across all ecosystems. Their reactive approach to web ui really allows me to develop complex interfaces in a maintainable way.
This became a longer message than I thought, probably due to my enthousiasm for the language. For complete transparency, the situation is not perfect, and in my experience the tooling is not the best.
If you want more info, I blogged about it a couple of months ago: https://www.asfaload.com/blog/consider-fsharp/
Lanayx a day ago
For reference, F# slack is already dead, community has moved to Discord https://discord.com/invite/fsharp-196693847965696000
kqr a day ago
Curious since you don't expand on it on the blog: in what way did Haskell's purity make it difficult to you?
Having used Haskell in production for a bit now, I don't even notice its purity. Most functions are in some kind of I/O context making it similar as other languages, except with the option of running without I/O capabilities for functions that shouldn't need it.
internet_points 20 hours ago
For me, Haskell's image and ideal of purity are what made it difficult when I started out. I tried learning the language by reimplementing a program I'd previously done imperatively, that was (in hindsight) obviously hard to do in a plain pure way, ended up learning about zippers and knot-tying to do something in a less efficient and more confusing way than just using something like STArray because I had this idea from reading about Haskell that this was not only a good way to do things, but would be magically fast because GHC. (It was not.)
These days I'd just do such a task more-or-less imperatively in Haskell, and I would be well guided by the types in doing so. But I also feel like you have to make a few such mistakes if you want to get a good intuition and taste for when it's good do things purely and when imperatively.
raphinou a day ago
I honestly don't remember as it was +/-6 years ago. I had started learning Haskell and got to that conclusion. Maybe that I am now more versed in FP I would arrive at another conclusion? I don't know.
Another thing that was hard to grasp for me were the special operators like =<<, ., $, etc. I was using Xmonad, but those operators create a barrier to understanding exactly what happened in the file.
In the end, F# was in my (personal) experience much more approachable, and it let me learn the functional concepts along the way.
blatantly 7 hours ago
What about libraries though? They might force you to use certain monads rather than IO?
kqr 5 hours ago
ninetyninenine 2 hours ago
Haskell taught me the important differences between IO and parity and forever influenced the way I program.
Even so the complexity here and the sheer number of mind bending concepts makes me not want to use it.
giraffe_lady 20 hours ago
You gotta remember people are often picking languages based on what they can easily find out about it and extrapolating/guessing about what problems they'll run into with their expected use.
A few years ago on here I had an interesting conversation with someone who wasn't going to use rescript for something because they didn't like how it handled object types. I can't remember ever using an object type in rescript; we all just convert js objects to record type in the extern binding. But that's not information easily available to someone who has never used the language.
Same thing here I think. If you don't already have familiarity with this paradigm, it's hard to imagine what using an IO monad for side effects is like. It's not easy to tell how hard it'll be to learn it, how much it may affect the rest of your code, etc. It's easy to imagine someone (shit even me a few years ago) going "eh I'll take the language with the big easy escape hatches just in case."
fredrikholm 11 hours ago
mike1o1 a day ago
There was a large group of folks that left Ruby on Rails for Elixir (even has a similar looking syntax), yet it wasn't on your list of languages to consider. Just curious, was there a particular reason?
raphinou a day ago
I should have mentioned in the message, but I was looking for a strongly typed language. I was an avid-user of dynamically-typed languages, but that particular Ruby on Rails app became unmaintainable, and part of the culprit was due to the dynamic typing. I hoped that using a statically typed language would make it easier to maintain a complex app in the long term. And I must say that it totally materialised, to the point that I don't want to develop in dynamically typed languages anymore.
Here's an example: as I said in my original message, I was a complete stranger to the dotnet ecosystem, and I learned the F# language at the same time. And I decided to develop the app as a library project to be used by the web app. I completely missed the prevalence of the async approach in the dotnet, and all my code was synchronous. One day, about half-way in the project, I realised I needed to switch to async code. Had this happened in a dynamically typed project, it would have been hell for me. Maybe it's me that can't grasp a project well enough, but I need the type-guardrails to find my way in large refactorings. And with the strong types, large refactorings can be done confidently. They don't replace tests, but make the refactoring process much more smooth.
The app is open source and its code is at: https://gitlab.com/myowndb/myowndb It doesn't have a lot of users, not the least due to lack of marketing and polishing the user experience. But I am satisfied of what I learned developing it!
DonaldPShimoda a day ago
tasuki a day ago
asadbeksindar 10 hours ago
breadwinner a day ago
Apache Spark, Delta Lake are written Scala. Being JVM based, it has a large ecosystem. Scala seems like a better choice than F#.
raphinou a day ago
I'm sure it can be the better choice, but for me it was not. It seems there was some incompatibility between me and Scala. I find it such a complex language and I never managed to wrap my head around it. As I said F# was my last choice at the start of my evaluation, and Scala was high on the list due to the Java ecosystem. But in the end it didn't work out for me.
F# on the JVM would be great though!
frakt0x90 a day ago
hurril a day ago
flakiness a day ago
apwell23 7 hours ago
michaelcampbell 21 hours ago
innocentoldguy a day ago
I think Clojure is the better option if you want to do FP using the JVM ecosystem. The problem (for me, anyway) I've run into with Scala is that it supports both functional programming and object-oriented programming. Every code base I've worked on in Scala has ended up being a hodgepodge of both, which I find annoying.
However, the best functional programming language is, of course, Elixir. :D
dkarl a day ago
raphinou a day ago
throw234234234 17 hours ago
michaelcampbell 21 hours ago
bozhidar a day ago
Great story! Thanks for sharing it!
rockyj a day ago
I did try F#, but I was new to .NET ecosystem. For 1 "hello world" I was quite surprised by how many project files and boilerplate was generated by .NET, which put me off.
I am all for FP, immutable, and modern languages. But then where are the jobs and which companies care if you write good code?
Now everyone wants languages which are easy to use with AI, while reducing workforce and "increased productivity". I have been programming for 20 years and know 4-5 languages, in India it was worse but in EU at-least I can make a sustainable living by writing Java / TypeScript. I cannot even find jobs with Kotlin + TypeScript which pay well, forget getting jobs in Elixir / Clojure / F# (there maybe a handful of opportunities if I will relocate for around 70K/year). That is why I have mostly given up on learning niche languages.
8s2ngy a day ago
I understand your perspective. I like to view niche languages as a medium for learning. For instance, I enjoy using Rust in my personal projects—even if many of these projects may never be released—because the lessons on immutability, functional programming constructs, and trait-oriented programming significantly enhance my day-to-day work. Therefore, I believe that learning niche languages, even in the absence of a robust job market, is worthwhile.
jen20 a day ago
I'm not sure I'd call Rust a "niche language" any more (perhaps in ~2018) - it's in common use across many big technology companies.
homebrewer a day ago
DeathArrow 8 hours ago
tester756 a day ago
>" I was quite surprised by how many project files and boilerplate was generated by .NET, which put me off.
With which language are you comparing with?
Because there's afaik csproj and maybe .sln
and both of them are let's be frank - foundational for almost all projects that arent just hello world.
Otherwise you end up with some cmakes or something similar that want to achieve something similar
owenm a day ago
I hear you on the opportunity side and I can't see that changing. The good news is in recent releases there's a lot less boilerplate - "dotnet new console -lang F#" results in two files, a short fsproj file and a single line of Hello World.
Foofoobar12345 a day ago
F# is quite usable with AI. All AI models are perfectly capable of generating idiomatic F# code. In fact, because it has a nice type system, if you ask the AI to model the problem well with types before implementing, hallucinated bugs are also easier caught.
elcritch a day ago
Same with Nim. It works surprisingly well with AI tools. I think both have more straightforward syntax so it’s easy to generate. I’m curious how more complex languages do like C++ / Rust.
Last time I tried C++ with Copilot it was terrible.
KurtMueller 14 hours ago
I find F# easy to use with AI, mainly because it's statically typed (which results in compiler errors when the LLM generates non-working code) and it's very expressive, which allow me to more easily comprehend what the LLM is trying to do.
raphinou a day ago
It is possible to start your project with the script possibilities offered by F# (as mentioned in the blog post). It is absolutely a viable approach and I even blogged about it a couple of months ago: https://www.asfaload.com/blog/fsharp-fsx-starting-point/
sodapopcan a day ago
> But then where are the jobs and which companies care if you write good code?
Oh man, that is poignant :( They always say they do in the job description, but it always a different story once you get there.
djha-skin a day ago
I learn them as a fun hobby, with no salary expectations. It keeps the dream alive, and I learn a lot from the Common Lisp community that I do use in my job.
afavour a day ago
Opportunities do exist, even when they’re few and far between. I learned Rust in my spare time because I was really interested in it. Then we stumbled across something that would have really benefitted from a cross platform library and lo and behold, I got to use my Rust knowledge, even though the vast majority of my day job doesn’t use it.
shortrounddev2 a day ago
I like F#'s syntax when all you're doing is pure logic. But when you have to interface with any IO like a database or REST call or something, you have to abandon the elegance of ML syntax and use these ugly computation blocks. In C# you can do something like this:
var post = await _postService.getById(id);
in F# the equivalent is basically let getPostById id = async {
let! post = blogPostService.getPostById id
return post
}
let post = getPostById 42 |> Async.RunSynchronously
But not really, because RunSynchronously isn't the same thing as `await`. Realistically if you wanted to handle the result of an async computation you would need to create continuations. F# isn't the only ML-family language to suffer from this; Ocaml does as well. It always seemed to me like the pattern with any asynchronous operations in F# is to either:1. Do all logic in ML-syntax, then pass data into a computation block and handle I/O operations as the last part of your function, then return unit OR
2. Return a C#-style Task<> and handle all I/O in C#
Either way, ML-style languages don't seem like they're designed for the kind of commercial CRUD-style applications that 90% of us find ourselves paid to do.
throw234234234 17 hours ago
I find it personally better for CRUD applications than C# and I've written my share in both languages. Your syntax comparisons aren't exactly comparable in the sense that you haven't put in the wrapping/boilerplate around the C# code - you can't just await anywhere. You are also using an async which to run needs to know which context - this can be nice when you don't want to run the composed Task/Async on the current sync context. These days you stick to tasks if you want C# like behavior - and there's libraries to take away some SyncContext overload via custom F# CE's if you want.
The equivalent C# to your F# would be
task { return! _postService.getById(id) }
Which is somewhat pointless anyway - just return the task from postService directly. There's also no need to run the async synchronously then - Async allow you to run the logic on task, thread, sync over and over - a very different model than tasks.To make C# comparable to your F# code (tasks are not the same so not quite true) you would need to define a method around it, and find a way if you want to run the resulting Task synchronously to do that safely.
public async Task<Post> GetPostById(id) => await blogPostService.getPostById(id);
// This is not entirely eq - since tasks are hot
this.GetPostById(42).Result
cjbgkagh a day ago
F# is a big language, it is a ML multi paradigm language that interoperates with C# so there is a lot of necessary complexity and many ways to do the same thing. A strong benefit of this is the ability to create a working functional paradigm prototype that can iteratively be refined to a faster version of itself by hot spot optimizing the slower parts with equivalent highly mutable functions while staying within the same language. Similar how one would use python and C++ and over time replace the python code with C++ code where performance is important.
For the specific case of C# use of await it is unfortunate that C# didn't design this feature with F# interop in mind so it does require extra steps. F# did add the task builder to help with this so the 'await' is replaced with a 'let!' within a task builder block.
let getById(id:int) : Task<string> = failwith "never"
let doWork(post:string) : unit = failwith "never"
let doThing() = task {
let! post = getById(42);
doWork(post); }
Alternatively the task can be converted to a normal F# async with the Async.AwaitTask function. let getPostById1(id:int) : Async<string> = async { return! getById(id) |> Async.AwaitTask }
let getPostById2(id:int) : Async<string> = getById(id) |> Async.AwaitTask
let getPostById3 : int -> Async<string> = getById >> Async.AwaitTask
neonsunset a day ago
malakai521 a day ago
`var post = await _postService.getById(id);`
the F# equivalent is
`let! post = _postService.getById id`
alternatex a day ago
smoothdeveloper a day ago
In C#, you can't use the await keyword in a non async method, so I find the argument short sighted.
jayd16 a day ago
shortrounddev2 a day ago
neonsunset a day ago
As sibling comment pointed out, it's just .fsproj manifest and Program.fs file. What boilerplate do you speak of? It's on the opposite end boilerplate-wise to projects made in e.g. Java or TypeScript.
For F#, projects are needed to make full applications or libraries. Otherwise, you can simply write F# scripts with .fsx and execute them via 'dotnet fsi {SomeScript.fsx}'.
(obviously you can also specify dotnet fsi as shebang and integrate these scripts into general scripting on Unix systems - it's very productive)
twodave a day ago
I suspect they were either referring to pre-.NET Core days before the new project formats came out or they're creating projects in Visual Studio and checking all the optional boxes. There indeed did used to be a lot more required boilerplate to get some code running. Now you can run a .NET project quite nicely in VS Code with 2 total files.
shortrounddev2 a day ago
protonbob 5 hours ago
I've found that as C# gains much of the features that F# has and will soon gain more (pattern matching, functions as first class data types, great fp libraries, etc) the "moat" that F# has over C# has gotten smaller. I write most of my c# code in a primarily functional style, but I still have the advantage of using the libraries in their own native ways that follow the examples given by microsoft and other vendors.
runevault an hour ago
Watching c# eat f# features as someone who has dabbled in f# lightly for over a decade has been wild. And supposedly DU's are in the works but multiple years out.
Though one thing I doubt c# ever gets that I love when I'm writing f# is pipeline operators. I love the way they read, from object/collection being worked on and then a list of operations being run on it in order from left to right (or you can do right to left if you need to for some particular reason).
darksaints a day ago
I'm completely convinced that F# (along with Scala, Haskell, and OCaml) adoption has stalled due to having ridiculously bad build systems. More significantly, they are being passed up in favor of Rust, which is a great language but nonetheless a bad fit for a lot of problem domains, simply because Rust has a superior build system. Hell, 80% of the reason I choose Rust over C++ for embedded work is because of the build system.
It baffles me that there are languages with non-profit foundations and are financially backed by multiple corporations which still have bad build systems. It is the most important investment you can make into a programming language.
jadenPete 16 hours ago
It’s always puzzled me that so many languages have their own build systems and package managers. Why aren’t programming language-agnostic build systems like Bazel and Buck more popular? It seems so strange that every new programming language essentially has to reinvent the wheel multiple times, inventing a new build system, package manager, formatter, linter, etc. I wonder if we’ll ever see something like LLVM for these technologies.
pjc50 3 hours ago
Firstly a strong desire to self-host: write the build system in the language itself.
Secondly, often very differently shaped requirements. The dotnet SDK tries to keep its build specification (.csproj) files editable by Visual Studio, which is why most of the stuff in them is just XML properties.
You probably could build C#/F# with Bazel but that's not what Microsoft chose, and you kind of need to stay aligned with them and the large amount of MSBuild files in the SDK.
Rohansi 4 hours ago
Because there are differences that go beyond just the language syntax. The build processes are very different for C++ vs. C#, vs. F#, etc.
C++: invoke compiler for all compilation units, invoke linker to combine object files into executable
C#: invoke compiler once with all source files listed
F#: same as C# AFAIK, except file order matters!
fodkodrasz an hour ago
Lyngbakr 20 hours ago
While I've never used it in anger, I really quite like dune. Was there something specific that makes you characterise it as "ridiculously bad"?
noahbp 16 hours ago
Not Dune exactly, but having to run 'eval $(opam env)' in the terminal every time you open an OCaml project rather than the default being npm-like, where you can just open the directory and use the package manager command without having to think about it.
anentropic 7 hours ago
johnisgood 4 hours ago
germandiago 4 hours ago
I use C++ with Meson and Conan and I can say that there is an initial learning curve if you need to adapt Conan recipes but once you get past, the results are quite good.
torginus 5 hours ago
My two cents is that F# hasn't received the same care and attention as C# and working with it can be awkward.
At the same time, a lot of the cool features (list comprehension, pattern matching, immutable records) have slowly trickled into c#, giving even less incentive to switch
fodkodrasz an hour ago
I personally find the way these features were shoehorned into the C# syntax an eyesore, I have quite some C# experience, and I think the language is getting more and more convoluted and noisy, with ever less coherent syntax.
On the other hand many of these features are really convenient and handy in F#. Adding many of the oh-my-gamedev-such-speed features from C# to F# also makes its syntax less pleasant to work with.
Personally I also think that the C# async model is terrible, and was a grave mistake. The F# async model with computation expressions, and explicit control over their execution context was a better approach, and I'm really sorry the hack-something-together to unblock the event loop WPF/frontend-dev usecase won over the more disciplined backend-focused approach.
throwaway2037 8 hours ago
> I'm completely convinced that F# (along with Scala, Haskell, and OCaml) adoption has stalled due to having ridiculously bad build systems.
Scala? I am not trolling here: Are you joking? Scala is part of the Java ecosystem. Sure, Maven gets lots of hate on HN, but it is very mature and has excellent integration with IDEs and CI/CD systems (TeamCity, Jenkins, etc.). In the last 10 years, many Java developers have moved to Gradle, which has equally good integration. > Hell, 80% of the reason I choose Rust over C++ for embedded work is because of the build system.
What is wrong with CMake for C++?dkarl 2 hours ago
Perl is mature, too.
Maven is awful. SBT is awful. Gradle is awful. I've used them all professionally, and the best I can say about them is that you can get the job done with them.
Newer languages and newer build systems are much better experiences, because of decades more hindsight and because language designers think about tooling from the start. Java was designed with the assumption that all software projects were built with Make, and with no ambition to improve on that. There was no Java-specific build tool until Ant was released as a standalone tool circa 2000.
> What is wrong with CMake for C++?
Granted, most of what's wrong with CMake is the problem it solves. Probably there's no solution that wouldn't be at least close to as awful as CMake. But it is objectively a hideous experience compared to any language created in the last 15 years.
oblio 7 hours ago
How long are Scala compilation times for a Hello World CLI, a Hello World basic webapp and for a reasonably sized production size code base?
My guess is that it's much longer than for the equivalent Java apps.
> What is wrong with CMake for C++?
It doesn't manage dependencies.
DeathArrow 8 hours ago
I would call .NET build system excellent.
fodkodrasz an hour ago
Lets settle on a finally good enough. I can give honest compliments on learning from the past problems and from the better examples in the indsutry.
You may not remember the early .net core times with yeoman and other then-current javascript ecosystem originated things applied in really cumbersome, half-assed ways, with lacking docs and always being in flux for years. The project.json era was terrible.
Also msbuild was way worse 10-15 years ago...
Mono with automake was special circle of hell IMO, I have very small exposure but it was really unproductive and painful.
pimbrouwers a day ago
Our shop converted 6 years ago, from C# to exclusively F#. I also author and maintain some packages (falco, donald, validus and others). The language is tough to learn if you're coming from a C-style language. But worth the effort and experience. It's extremely concise a true delight to build programs in that are fast, robust and durable.
There are a few drawbacks, depending on your perspective:
- compilation is slower than c# and hot reload isn't supported (it's in progress)
- there are very few opportunities to use it professionally
- hiring devs can be challenging
Foofoobar12345 a day ago
Hiring devs is perfectly fine if you don't look for F# skills - just hire generally smart people, and allow them 1-2 weeks to get comfortable with F#. Make them just solve problems from project euler or something.
For those who have already done functional programming, they wont take more than 2 days to start getting productive. For those who have written a lot of code, it will take them ~2 weeks to pick up functional thinking.
Anyone who is still uncomfortable with F# after 1 month - well that's a strong signal that the dev isn't a fast learner.
Additionally, I've never had anyone reject our job offer because we do F#. I'm sure a whole bunch of people might only be looking for python or javascript jobs, but that's fine because I'm not looking for them. I always have more people who I want to hire but I can't due to budget constraints.
Source: direct experience - I run a pure F# company with a team size of ~80.
CharlieDigital 6 hours ago
> Anyone who is still uncomfortable with F# after 1 month - well that's a strong signal that the dev isn't a fast learner.
I think you may be reading this wrong. Agree with sibling post that even teaching folks C# -- which isn't far off of TypeScript, Java, etc. -- is never so straightforward if the individual wants a full grasp of the tool.For myself, I feel that I have "full" command of C# as a programming language, but also how to structure projects, how to isolate modules, how to decouple code, how to set up a build system from scratch for C#, how do deploy and scale applications built with C#, what the strengths and weaknesses are, etc. My definition of "comfort" would entail a broader understanding of not just the syntax, but of the runtime ecosystem in which that code operates.
Kwpolska an hour ago
The problem is, many recruiters don't work with this mindset. If they're hiring a Java developer, and they get a CV from someone who has 1 year of Java experience and 5 years of C# experience, they see 1 year of experience, and immediately put it on the "unqualified" pile.
GiorgioG 5 hours ago
For me, my discomfort with F# is due to not knowing if what I’m doing is the correct/idiomatic way of doing things. With C# I have learned all the ways I should not do things…so it’s easier/faster to just use C#.
pimbrouwers 18 hours ago
Hi Isaac ;) Of course you can train people. But in my experience they take a lot longer to learn than you suggest.
z5h a day ago
As a proficient Elm developer with industry experience, I’m wondering what are the biggest challenges in hiring devs? Is it the paradigm, learning the ecosystem, lack of interest? Are you currently hiring?
Akronymus a day ago
As someone who quite likes f#: It seems like a chicken and egg problem, not many companies doing f# because not many devs know it and not many devs learning it because not many companies are doing it.
I certainly wish I were doing f# professionally, but I only ever found 1 job listing for it, and that was in vienna while I am located like 200km away from it :(
Speaking of elm: I really like elmish for the frontend, when I need to make a dynamic page in the first place. Maybe that could be to your interest? (It transpiles to react under the hood via fable, which you can webpack into a drop in bundle. But I digress)
DeathArrow 7 hours ago
Jobs are kind of rare. I have to learn F# hoping maybe I will find a job in one or two years. And if I find it, they might want someone with F# work experience.
cogman10 a day ago
How does the typing system work for F#?
From the article, it looks like it's mostly dynamically typed. Or is it inferred? Or is it something else?
Like, if I write
let hello value =
print value
hello "world"
hello 2
Does that just work?To me, that'd be a point that might steer me away from the language. Deducible types seem vital to larger and long lived projects.
Nelkins a day ago
It's statically typed and inferred.
With regards to your example, the print/printfn (equivalent of Write/WriteLine) functions are a bit funny in F#. They don't actually take bound string values directly. You need to specify the type (which could be a string, a number, obj, etc)
https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref...
neonsunset a day ago
F# is a statically typed language with gradual typing and full type inference.
Given
let hello value =
printfn "%A" value
hello "world"
hello 2
The binding "hello" has "'a -> unit" signature where 'a is a generic argument it accepts because the "printfn" binding with a given format specifier is generalized the same way and an unconstrained 'T (here 'a) is the most narrow type inferred for "hello".debugnik 4 hours ago
foretop_yardarm 17 hours ago
Thanks for your work on falco, it’s a really great library.
DeathArrow 8 hours ago
>- there are very few opportunities to use it professionally
- hiring devs can be challenging
Those drawbacks are huge, IMO.
lihaoyi a day ago
I learned F# in 2013 and had a lot of fun with it, some of that code remains on Github (e.g. a 2D platformer game for windows https://github.com/lihaoyi/FSharpMetro/tree/master/Applicati...).
My experience was that it was a surprisingly nice language with a surprisingly warty user experience: papercuts ranging from naming conventions and function call styles (`|> List.map` vs `.Select`), basic syntax (`foo.[0]` to lookup arrays), type system features (F# doesn't have covariance/contravariance even though C# does), IDE support (back then was only Visual Studio, whose support for F# was inferior to C#).
Ended up settling on Scala after that, as a language with its own Warts, but one that somehow managed to feel a more cohesive than F# did despite having largely the same featureset and positioning.
F# was my first functional language and one that changed how I look at programming, but at the same time I'm happy to not actually have to use it for serious programming!
munchler a day ago
F# supports both functional and OO call styles. That's why you have both `|> List.map` and `.Select`. It can be a bit confusing at first, but the interoperability with C# is worth it.
Array lookup in modern F# is just `foo[0]`.
Subtyping is much less common in F# than in C#, so the need for covariance/contravariance is correspondingly lower. Personally, I've never needed it.
F# support in Visual Studio is now excellent. You can also develop F# in VS Code.
JohnyTex a day ago
FWIW I think writing F# is a really cohesive experience in day-to-day work. While there are usually at least two ways to do things, due to .NET interoperability requirements, it’s usually pretty clear which way is the “right” way to do something.
F# feels kind of similar to Python in this regard, where there might be more than one way to do it, but there is community and ecosystem consensus on what is the right way.
I think a lot of credit should go to Don Syme for this; he seems to have a very clear vision of what F# should and should not be, and the combination of features ends up being very tasteful and well composed.
bozhidar a day ago
I think these days F# is probably a big more polished than what you remember, so perhaps it's worth giving it another shot.
Being a hosted language always requires certain compromises (something that was also apparent in Scala). I used to do Scala professionally in its early days, but for me it felt it added just as much complexity as it addressed. I focused on Clojure back then (on the FP side at least), and I do think that F# probably brings more to the table than Scala. (if one is not constrained to Java, that is)
The tooling story is not great, but I've almost never seen great tooling for a language that's not super popular. I'm guessing what you get today with Rider is more or less as good as what VS has to offer.
djtango a day ago
Interesting - I'm curious where your thoughts are now on using FP/Scala in 2025?
I've always looked at F# with envy as it is a hosted ML that will have extremely battle tested bindings to the important day to day stuff via C# (Darklang's stories of struggling with postgres and AWS when using OCaml was a good cautionary tale on the risks of using less common langs as a startup)
Never had a chance to try out Scala but am a seasoned Clojurian, as an outsider it seemed Scala suffered a little from being not opinionated enough so the ML family has been more appealing to tinker with even though Scala supports type classes out the box and will also have great ecosystem support via the JVM
hocuspocus a day ago
It's never been a better time to try Scala if you're interested in the FP side. It's still very much "not opinionated" but the community and ecosystem have benefited from a certain convergence and given up on the "better Java" front which is served by Kotlin more adequately. Of course you can still consume any Java library when needed but it's best to avoid it if possible. Today you can pick between several ecosystems:
- Typelevel libraries: modern and more welcoming take on ScalaZ ideas, rich and mature, extensible libraries that are written in "tagless final" style.
- ZIO: concrete "super monad" with 3 type parameters, shuns the Haskell baggage and category theory lingo but pretty much the same concepts, compile-time autowiring dependency injection, a bit less mature.
- Kyo: new effects system on the block, pushing Scala 3's type system to the limit to stack effects using an "auto-flattening" monad (sorry if I butchered the description).
- Li Haoyi's own ecosystem that sticks to the standard library and JVM built-in mechanisms whenever possible, focused on Python style expressiveness, only more functional and with stronger types.
- I'd skip Akka/Pekko libraries but it's still an interesting piece of software if you need actor based, stateful cluster sharding.
Martin Odersky and the LAMP are focused on "capabilities" and we should eventually see something like direct-style algebraic effects, or like Kyo but without monads.
Also we have much better build systems than before (Scala-CLI, Mill, sbt has improved a lot too), binary backwards compatibility since Scala 3, and a very capable LSP backend if you don't like IntelliJ IDEA.
DeathArrow 8 hours ago
tasuki a day ago
eknkc a day ago
As far as I can tell F# is one of those things where every single user is extremely happy. This happens rarely and I really am curious about the thing but never had time to get into it. I'm also pretty well versed in the .net ecosystem so it's probably gonna be easy.
Any tips? What kind of workflows might benefit the most if I were to incorporate it (to learn..)?
pjc50 a day ago
The funny thing is that you can write very similar code in C#, so maybe you don't need to switch which language you're using as a CLR frontend.
using System.Linq;
using System;
var names = new string[] {"Peter", "Julia", "Xi" };
names.Select(name => $"Hello, {name}").ToList().ForEach(greeting => Console.WriteLine($"{greeting}! Enjoy your C#"));
LINQ is such a good library that I miss it in other languages. The Java stream equivalent just doesn't feel as fluent.issafram 8 hours ago
You're being way too nice. Java stream is nowhere near as easy to use as LINQ. I'd say that LINQ is easily one of the top 10 coding features that Microsoft has ever created.
DeathArrow 5 hours ago
psychoslave a day ago
As far as fluency goes, that’s not very impressive.
%w{Peter Julia Xi}.map{"Hello, #{it}"}.each{puts "#{it}! Enjoy your Ruby"}
That’s of course trivial examples. And while Ruby now have RBS and Sorbet, it’s yet another tradeoff compared to a syntax that has upfront static analysis as first class citizen in mind.That is, each language will have its strong and weak points, but so far on "fluency" I’m not aware of anything that really beat Ruby far beyond as Ruby does compared to other mainstream programming languages.
int_19h a day ago
bob1029 a day ago
You can write a vast majority of your C# codebase in a functional style if you prefer to.
All the good stuff has been pirated from F# land by now: First-class functions, pattern matching, expression-bodied members, async functional composition, records, immutable collections, optional types, etc.
int_19h a day ago
UK-Al05 a day ago
guhidalg a day ago
klysm a day ago
This isn’t a great example of what linq is good at. There’s no reason to do ToList there, and the ForEach isn’t particularly idiomatic
pjc50 a day ago
bob1029 a day ago
DeathArrow 5 hours ago
kkukshtel a day ago
Modern C# collection expressions make the definition of names closer to F#:
string[] names = ["Peter", "Julia", "Xi"];
I know working on "natural type" of collections is something the C# team is working on, so it feels possible in the future that you'll be able to do this: var names = ["Peter", "Julia", "Xi"];
Which I think would then allow: ["Peter", "Julia", "Xi"].Select(name => $"Hello, {name}").ToList().ForEach(greeting => Console.WriteLine($"{greeting}! Enjoy your C#"));
pjc50 a day ago
voidUpdate a day ago
I love LINQ, maybe a little too much. I can end up writing monster oneliners to manipulate data in just the right way. I love list comprehensions in python too, since they can work in similar ways
EVa5I7bHFq9mnYK 11 hours ago
That could be shortened to
names.ForEach(name=>Console.WriteLine($"Hello, {name}! Enjoy your C#"));
gibibit a day ago
For reference, Rust provides a similar experience
let names = ["Peter", "Julia", "Xi"];
names
.map(|name| format!("Hello, {name}"))
.iter()
.for_each(|greeting| println!("{greeting}! Enjoy your Rust"));
munchler a day ago
F# shines on the back end, where its functional-first style is very adept at crunching data. Think about data flows in your system: Any place where you use LINQ in C# today to select/filter/transform data might be even better in F#. Parsing is also a great F# use case (e.g. parser combinators), although a fairly narrow niche.
JohnyTex a day ago
Personally I think F# is excellent for writing ye olde CRUD applications, especially as the business logic becomes more complex. F# is really good at domain modeling, as creating types comes with minimal overhead. C# has improved a lot in this area (eg record types) but it’s still got a long way to go.
I wrote a tutorial about how to get up and running with web dev in F# that might be of interest: https://functionalsoftware.se/posts/building-a-rest-api-in-g...
DeathArrow 5 hours ago
Thank you, for someone interested in using F#, that is great.
I see you use Giraffe but I wonder how hard would it be to use Web API or to mix F# projects with C# projects in the same solution.
piokoch a day ago
"As far as I can tell F# is one of those things where every single user is extremely happy" Isn't it because language has rather small community of passionate people, who are devoted to their language of choice?
F# popularity is somewhere between CHILL, Clipper and Raku langs, that are probably as obscure as F# for typical software dev.
int_19h a day ago
I'm pretty sure that there's more production code written in F# than in all those other three combined.
psychoslave a day ago
I know Raku from Perl fame, and F# because it’s Microsoft, but CHILL and Clipper are totally new to me, so in my own humble experience these two latter look far more obscure. :D
orthoxerox 20 hours ago
DeathArrow 5 hours ago
If we consider number of jobs, it's probably on par with Rust.
reverseblade2 a day ago
Here's a Saas that actually makes money written fully in F#
Here's a rust ray tracer compiled to web assembly written in F#
https://ncave.github.io/fable-raytracer/
source: https://github.com/ncave/fable-raytracer?tab=readme-ov-file
stefanfisk a day ago
The navbar takes up half my screen on an iPhone 13 mini :/
kingkongjaffa 20 hours ago
F# is great
Even if you never write a single line, it’s a fantastic illustrative language.
For example I refer to https://fsharpforfunandprofit.com/ all the time for functional programming ideas.
7thaccount a day ago
F# is beautiful, but I could never crack the nut and get fluent in it. I think the big problem is I only know a little C#, so it is difficult to figure out the object oriented methods that F# depends on. It was the same thing with Clojure and Scala for the JVM. I have zero interest in first learning C# or Java, just to use those platforms.
diggan a day ago
> It was the same thing with Clojure and Scala for the JVM. I have zero interest in first learning C# or Java, just to use those platforms.
FWIW, I managed to learn Clojure without knowing anything from Java/JVM before diving into it. I did have plenty of JS experience which made ClojureScript easier to pick up I suppose, but Java works more or less the same as every other Algol-like and/or OOP language out there so if you have any previous experience with something like that, basic Java is trivial to pick up even accidentally.
netdevphoenix a day ago
you are not supposed to do oop in f#
7thaccount a day ago
I'm aware, but you need to understand the .NET ecosystem to get anything practical done (at least when I was using it in 2017). All the books written on it (I own 3) are also the same way and assume you're a skilled C# dev.
miloandmilk a day ago
hajile a day ago
F# depends heavily on existing C# libraries and those are all OOP.
smoothdeveloper a day ago
genter a day ago
Except that there's a huge number of libraries written in C# that are available to F# (since both run on the CLR), and you have to do OOP in F# to use them.
shortrounddev2 a day ago
FP and classes are not mutually exclusive
ninalanyon a day ago
Why not? It does it very well, better than C# in my opinion. At least that was the case ten years ago when I last used C# and played with F#.
zem a day ago
oop is just another tool in your toolbox; if f# provides it and it's the best way to express a given algorithm you should definitely go ahead and use it. oop got a bad name due to people trying to shoehorn it into places it was not the best way to express something, and it seems like you're making the inverse mistake here.
jonsagara a day ago
The killer feature for me is type providers. I need to read a lot of CSV files of varying formats, and the CSV Type Provider lets me make quick work of them in a type-safe manner.
https://fsprojects.github.io/FSharp.Data/library/CsvProvider...
Hojojo a day ago
Wow, that sounds awesome. I'm jealous.
a-french-anon a day ago
Why would Lispers feel at home with its (whitespace delimited) syntax? Quite the strange claim.
I know this isn't a common rant, but I hate so-called functional language still bowing to the "infix mathematical operator special case" dogma, when those are just binary (variadic in Lisp) functions.
Always found it pretty appealing, otherwise. And no ";;"!
110bpm 21 hours ago
I put together a quick-start guide to F# Computation Expressions — showing how you can go from C# async/await all the way to Result<> workflows with let!... and!... expressions, and even a custom validation {} CE. [0]
This is a practical side of F# that doesn’t get enough spotlight — but one I’m using daily.
shermantanktop a day ago
> Trivia: F# is the language that made the pipeline operator (|>) popular.
I’m not a dabbler in exotic languages, so this definition of “popular” was puzzling. I’ve literally never seen that operator before. Maybe I need to get out more.
zdragnar a day ago
It exists in several similar languages such as elixir, and was even a proposal for ecmascript, but never really got traction.
sundarurfriend a day ago
I'm familiar with it via Julia, and I believe recent versions of R also have it.
WorldMaker a day ago
It made it to Stage 2, which is some traction: https://github.com/tc39/proposal-pipeline-operator
It has been "stuck" at Stage 2 for a while, though.
shermantanktop a day ago
hurril a day ago
F# is a wonderful language, one that I write as my daily for the second time during my carrier. It _baffles_ me how it isn't more popular than it is because it truly is very very good. And I say this as an experienced and avid functional programmer.
We even do the frontend in it using Fable and Elmish, which is to say: we basically write our frontends in Elm, but the platform is .NET.
protonbob a day ago
> which is quite odd for what is supposed to be the flagship editor for F#
The flagship editor is Visual Studio, not vs code.
MaxGripe a day ago
The flagship editor is Rider
bozhidar a day ago
But it's Windows-only, so it's not an option for me.
GiorgioG a day ago
Rider is an option for you. Community edition is free too.
LandR 8 hours ago
protonbob a day ago
Who said it was? It is the flagship editor though.
neonsunset 5 hours ago
Why not VS Code with Ionide? It’s quite nice.
mesic 5 hours ago
F# is getting some traction in Norway. I know for a fact that places such as NRK (BBC eqvivalent), Resoptima, Frende Forsikring and my current employer, REN are all using F#.
I just gave a talk about how we use F# at REN: https://vimeo.com/1070647821
rawoke083600 8 hours ago
I'm waiting for the excellent F# Article about railroad-coding to be posted here. Required F#e reading :) No not trolling. Am on mobile and traveling else I would have searched-posted
smcl 8 hours ago
I assume you're talking about Scott Wlaschin's "Railway Oriented Programming": https://fsharpforfunandprofit.com/rop/
nickpeterson a day ago
Because it’s great, and people that think otherwise are dead to me.
MrMcCall a day ago
Curried functions combined with that magnificent pipe operator, overlaid on the .NET runtime. Don Syme et al knocked it out of the park.
It's the one programming language that changed how I think about programming.
I'm only talking about the version before type providers. Then it got messy.
Before that, we could (and I did) recompile fsi.exe to do some custom prompt manipulation. It was a slog, but it worked, but then Microsoft faded from my life. Still, that early version (I believe 2.0) F# is just magnificent.
munchler a day ago
F# is up to version 9 now, and has only improved over time, IMHO. Type providers are a very small part of the story and can be avoided entirely if you want.
jasonthorsness a day ago
speed_spread a day ago
MrMcCall a day ago
akkad33 21 hours ago
It has great ideas but because of all these conveniences it is very bad for performance based programming making it slower than C#. I like the ideas in Roc language to make functional programming as fast as imperative by controlling allocations in things like closures
MrMcCall 8 hours ago
turtlebits a day ago
It might be great, but IME, MSFT docs and tooling are subpar, and anything dotnet related is/was a disaster.
GiorgioG a day ago
As a 20+ year C# developer I’ve tried several times to learn/use F#. Despite being interested in FP, my brain is having trouble figuring out how to structure my code in F#. In C# I’d either build a service (or use the mediator pattern) for the domain and a repository for data access. With F# it’s functions all the way down and it feels unnatural (as silly as that may sound).
Akronymus a day ago
along with what jcmontx said: F# is structured bottom from top. As in you can't reference something that is later defined earlier. I find that naturally leads to getting a decent enough structure "for free" because it forces you to have your basic functionality early on and build on that later.
That also, IMO, makes untangling/splitting up parts of the codebase easier as well.
jcmontx a day ago
The secret is currying. Replace your DI for currying and you'll start to see somewhat similar patterns
Smaug123 a day ago
By the way, I consider https://www.bartoszsypytkowski.com/dealing-with-complex-depe... to be the canonically correct way to do DI when you want to inject more than like two dependencies.
DeathArrow 4 hours ago
Have you tried using a book or a tutorial to see how things can be done using idiomatic F#?
MrMcCall 19 hours ago
That makes sense when one is used to the Visual Studio organization of solutions and projects, with some main method somewhere being the entry point, unless it's a WCF service or somesuch that gets run via a service manager.
I only used F# at its command line, fsi.exe, to give me commandline access to .NET for exploration, testing, and munging data. Over time, I built up quite a library of usable functions that I'd have the fsi.exe program pre-load when I kicked it off, leaving me at the prompt with all .NET namespaces and my code ready and accessible.
Once you get access to your database's data, it's easy to write queries against it and then play with the data. I could then port the F# processing bits that worked into my C# projects as necessary, but it was far easier to do it that way than to write the logic deep within complex multi-project solution files, where the various classes are spread throughout the projects' files.
I also just really enjoyed using F#.
BenGosub a day ago
Two nice things about F# are that you can introduce it into an organisation using the dotnet ecosystem and that you can use all libraries in dotnet, which is a huge advantage over OCaml.
Otherwise, I am happy with OCaml, but F# has also a place in this world.
UlisesAC4 10 hours ago
You can use adapters via Foreign Function Interface and interact with C++ code. The deal breaker is that memory is separated, C++ code has its own heap and Ocaml too. Quiet different to F# in which operating with C# is seamless and the runtime is the same.
DeathArrow 4 hours ago
You can call C++ code from F#, too.
justanotheratom a day ago
F# was my favorite language, but - You have to chose the language of the Domain that you are working in, e.g, Swift for native iOS Development. Supabase Backend requires TypeScript, etc. - LLMs don't care about F#.
aaronmu a day ago
I've been using F# professionally for the past seven years across different contexts. First in a small software shop and now while bootstrapping a SaaS company. Some observations:
* It’s easier to attract smart developers to an F# project than to a [mainstream language] project. This was one of my driving beliefs when I introduced F# seven years ago. https://www.paulgraham.com/pypar.html. This is probably just as true for languages like Elixir, Clojure, ... But F# is what we went with.
Small Software Shop Context
* We operated in a small market where customers eventually dictated our tech stack (.NET & React). In that market, F# was a major advantage—it allowed junior developers to build apps that "just worked" with minimal regressions. Even with mediocre code quality, I felt confident that we could refactor safely at any time.
* I constantly had to justify F# to clients, which was exhausting. We always delivered decent results, so it worked out, but my partners were never as confident in defending F#.
Bootstrapping a SaaS Company
* F# has been invaluable for shipping features quickly and taking shortcuts when needed.
* Three years in, our codebase is large and contains its fair share of messy parts. But we can still develop new features at high speed with minimal regressions. Refactoring is relatively safe and straightforward.
* Compilation speed is the Achilles’ heel. If you don’t monitor it, the compiler slows down to the point where it impacts productivity. Earlier this year, waiting over a minute for feedback after a small change became unbearable. A lot of our "clean-up" work focuses on optimizing compilation times. We're still learning, but we’re optimistic that we can restructure the project to significantly improve build performance.
EDIT: maybe one more point. I see a lot of C# vs F# popping up here. Yes, C# has all the features that F# has. But do not underestimate how well designed F# is. It is an extremely simple language to learn compared to C#. There is a very limited amount of keywords to learn. And they compose extremely well. If you learned F# 7 years ago, took a break, and came back today, you'd simply write the same boring code that you would have written 7 years ago. And along the way you'd find out that some things have gotten a bit nicer over time.
nickpeterson a day ago
I’ll add that features isn’t really a constructive way to think about the differences between C# and F#. C# has more ‘features’ than most other programming languages. One of the core features of F# is less features and churn. Also, I really appreciate the way F# maintainers agonize over how to maintain the language and keep it coherent. You don’t get the feel they’re chasing features at all.
GiorgioG a day ago
As a 20+ year C# dev...where do I learn how to structure apps in F#? In C# my ASP.NET Controller might use a service (or a mediator) to execute some domain logic and that in turn will use a repository pattern (or EF DbContext) to update/query a database. How are dependencies injected in? It seems like there are multiple ways of going about it, but I don't have enough knowledge of F# to know 'the proper way' to do it.
Lanayx 15 hours ago
I wrote an article about it. https://medium.com/@lanayx/dependency-injection-in-f-the-mis...
JohnyTex a day ago
The situation is a bit more complex in F# than C#, as there are multiple ways to do it. Scott Wlaschin has a good overview post about it here:
https://fsharpforfunandprofit.com/posts/dependencies/
FWIW you can do it exactly the same way you do it in C#; it’s not “wrong”, it might just feel a bit out of place.
systems a day ago
The problem with F#, Clojure and Elixir (hosted languages)
For F# , you need some basic C# knowledge For Clojure, you need some basic Java knowledge For Elixir, you need some basic Erlang knowledge
I like all 3 languages but usually each vm have a primary language, and each hosted language eventually become hosted on that primary language not the vm
I understand that for many task simple, to medium complexity, you might not need that, but it seem as you try to be more advanced you hit the wall of having to learn you host vm primary language
skrebbel a day ago
> For Elixir, you need some basic Erlang knowledge
As an Elixir programmer, this does not resonate. Basically the only thing I've ever felt I needed to understand Erlang for was ets, but let's be honest, that's not really proper Erlang but just the terrible ets query syntax. And all this requires is "ability to read enough erlang term syntax to be able to understand the ets manual". I don't think I could write a single line of correct Erlang by heart.
I feel like that's different in F#, where you still need to know lots of .NET internals which are all documented in C#y terms with C# examples etc. Elixir wraps pretty much all good Erlang/OTP internals in nice Elixiry modules, which solves that quite nicely.
Elixir has its warts but this really isn't one of them.
graemep a day ago
Thanks. I know a bit of Erlang (put some effort into learning, but never used it in real life, probably forgotten what I learned) and want to learn Elixir which seems better suited to what I want to do in the short to medium term.
iLemming 2 hours ago
> For F# , you need some basic C# knowledge For Clojure, you need some basic Java knowledge For Elixir, you need some basic Erlang
Honestly, none of this really rings a bell. Having used all three options, I never felt that. Well, I already knew C# before getting into F#, but honestly, it felt like my C# knowledge at the time was more of a distraction. Been using Clojure for nine years, never done any serious Java and have not felt any need for it. Not knowing Erlang wasn't a problem with Elixir, like at all.
LandR 8 hours ago
I've written a lot of Clojure now, and I've managed to avoided learning any Java really.
chamomeal 3 hours ago
That’s a reassuring thing to hear as a new clojure learner who has little interest in java.
What bits of java have you ended up needing? Like do you often use java libraries that don’t have clojure wrappers?
I feel like I’m often running up against little things. I’ll google “how to do xyz in clojure” and the top SO answer is to use a java library that apparently everybody already knows about, cause so many clojurists came from java first!
iLemming 2 hours ago
graemep a day ago
Erlang is not a difficult language. Unusual, but actually quite sane syntax. If you are already familiar with Elixir it would probably be pretty easy to learn the basics of Erlang.
innocentoldguy a day ago
I worked with Elixir for over five years without knowing anything about Erlang. I know Erlang now, but only because I was interested in learning it, not because I needed to do so to write Elixir code.
lysecret a day ago
I worked a lot in F# and loved it. I love that it has a lot of great functional ideas without being too pedantic about being 100% functional all the time. (You can have mutating state or just call arbitrary C#.) I took a lot of its insights into my daily python code too. I especially love match.
mrkeen 21 hours ago
There's no need to be functional 100% of the time, and it's not pedantry.
You mark your functions and non-functions as such, so the compiler can get your back.
DeathArrow an hour ago
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.
phplovesong a day ago
Last time i tried F# i got bit by the weird concurrency story. There was async/task and somwhow they did not play well together. Also the dev tooling (for vim) was subpar, compared to ocaml (lsp). Compile times also was on the slower side.
110bpm 21 hours ago
`async` is F#'s original implementation of async programming. It is the precursor to C#'s await/async.
`task` targets the .NET TPL instead, which is also what C#'s await/async and all of .NET *Async methods use.
While the `async` implementation still offers some benefits over `task` (cold vs. hot starts [0]), my advice is - if you're doing backend code on .NET, you should use task. The tigher integration with the .NET ecosystem & runtime results in better exception stack traces, easier debugging and faster performance.
[0] https://github.com/TheAngryByrd/IcedTasks?tab=readme-ov-file...
neonsunset a day ago
If you use task { } CE's you will get really good UX (it is recommended to use them over async CE's). They were introduced in F# 6.0 to address outstanding interoperability issues. As of now, writing asynchronous code is more convenient than C# (which is more convenient than Go or other languages which are less expressive w.r.t. writing highly concurrent code).
gwbas1c a day ago
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?
debugnik a day ago
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.
neonsunset a day ago
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 a day ago
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 a day ago
Aldipower a day ago
"Why the F#?" perhaps would be a better title. :-)
aloisdg a day ago
F# is corporate friendly ML. Love it.
twodave a day ago
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 17 hours ago
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 20 hours ago
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#.)
DeathArrow 3 hours ago
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 a day ago
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 a day ago
Can you give an example of said boiler plate?
marcosdumay an hour ago
DeathArrow 2 hours ago
gwbas1c a day ago
> 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 a day ago
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 a day ago
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 20 hours ago
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 2 hours ago
malakai521 a day ago
A nicer, cleaner and simpler syntax, superior pattern matching, active patterns, discriminated unions and computation expressions
int_19h a day ago
C# has the equivalent of active patterns these days.
malakai521 a day ago
amelius a day ago
I have a few questions. Can it do GUIs well? How about mobile? And how does it compare to e.g. Scala?
dagw a day ago
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.
Lanayx 21 hours ago
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...
pjc50 a day ago
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.
ivm a day ago
.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 a day ago
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 a day ago
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 a day ago
Sprinkle some HTMX next to your favorite template engine and you're g2g
Akronymus a day ago
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
jxjnskkzxxhx a day ago
Does anyone else find interesting that people who write blog posts saying "my favourite language is X", it's never a mainstream language..?
iLemming 2 hours ago
> people who write blog posts ... never a mainstream language
Don't you find it amusing that food critics usually write about little-known or new restaurants and never do any fast-food chain reviewing?
mrkeen 21 hours ago
Successful language designers select for what's popular, not what's good.
C++ intersected the mass of C programmers with the new OO fad, and kept all of C's warts. Had Stroustrup made C++ better, he wouldn't have an army of adopters who already knew C. Maybe merit will win out in the long run [1]? I'm not hopeful.
Java needed to be close enough to C++, and C# to Java. And Brendan Eich joined Netscape to "put Scheme in the browser".
[1] https://www.theregister.com/2025/03/02/c_creator_calls_for_a...
pantsforbirds a day ago
My favorite language is Python, but I wouldn't write a blog post about it because no one would care.
jxjnskkzxxhx a day ago
My favourite language is also python, and I would love to read your blog post on why your favourite language is python :-)
siknad a day ago
New mainstream languages are rarer than new better (in some way that can be favorable) languages.
sklivvz1971 20 hours ago
As a person who's worked with the author (a great guy!) and with the F# community on a very large F# project: don't bother with F#, professionally speaking.
F# has many theoretical qualities, which make it fun if you like these things, but it also has some fundamental flaws, which is why it's not getting a wide professional adoption.
- the build system was a mess last I checked (slow, peculiar)
- syntax is not c-like or python-like (a big deal for a lot of people)
- you can't hire developers who know it (and certainly the few are not cheap)
- the community is a bit weird/obsessed/evangelizing (a turn off in a professional environment)
- it's clearly a second class citizen in the .net world (when stuff breaks, good luck getting support)
On the other hand
- it has discriminated unions
- units
- etc.
but do you need this stuff (not want: need)? most people don't.
debugnik 4 hours ago
The build system is exactly the same as C#, MSBuild with its .NET SDK, and syntax and community are entirely subjective; F# has the least weirdo community I've personally seen for an FP language. Weak arguments to say the least.
I'll give you the chicken-and-egg hiring problem and it being second-class to the .NET team, though; I'd add poor IDE support by modern standards, only Rider feels right. I love F# but I've moved on for these reasons.
DeathArrow 9 hours ago
Iove the ideas behind functional programming but I never properly learned a functional programming language. I will probably never have the opportunity to use it professionaly and learning it just for hobby doesn't make sense to me.
If I am developing something in my spare time I also like to use something I can earn money with so I can hone and maintain my earning skills. Maybe sounds like min maxing.
If I would be in a situation where I can develop software just out of pleasure or pure curiosity, I would use just whatever language I deem interesting.
FrustratedMonky 18 hours ago
F# on front page? And popular?
ahhh, Its April Fools?
JK, I love F#. Please get over the hump and be a big language.
pdimitar a day ago
People will do anything except actually try Elixir. :D
...I mean: pipes, immutability, transparent mega-parallelism... helloooo?
I tried F# some years ago (after I was fired from a shop that decided they will go all-in on Java and F# and dropping everything else overnight) and I was not impressed. I mean the language is really nice but the C# baggage and runtime was just a bit much. And I was not left convinced that immutability alone is worth the switch. I suppose we can call F# an FP gateway drug?
Now arguably you get a runtime and some baggage from the Erlang runtime (the BEAM VM, where Elixir also runs), but the guarantees and features you get are invaluable, and have proven themselves many times over the last literal three decades.
xigoi a day ago
Elixir is dynamically typed, which presumably many people are put off by.
pdimitar a day ago
Yes, I agree that it's a big drawback.
Elixir made me more productive and gave me back my love for programming, and I work with it professionally for 9 years now. But the lack of static typing is getting so irritating that I started upping my efforts to get [even] better at Rust lately.
So I agree. It's one of the very top drawbacks of Elixir.
weakfish a day ago
The shop went all in on Java and F#? Why not C# and F#? That’s really odd, unless there’s context I’m missing.
pdimitar a day ago
I wish they told me. They cut ties with most of their previous devs overnight, as if we were some enemies. Weirdest firing in my life and career to this day.
weakfish a day ago
johnnyjeans a day ago
> Elixir
For me, it's Erlang. I just really like its horn clause syntax, it's so clean and readable. I know a common complaint is lack of piping (and even though you can implement it trivially, the order of arguments for some functions makes it of dubious use) but it's a small price to pay.
> I mean the language is really nice but the C# baggage and runtime was just a bit much
This was my experience with F#. Frankly, I've never been happy with my experience with CLI on Linux, and the toolchain inherits a lot of baggage from its C# heritage. Microsoft's toolchains have a very distinct workflow to them. F# has some interesting aspects to it like active patterns (something I wish was more common in the ML-family), but tbh I'm more than happy with ocaml.
innocentoldguy a day ago
I can't remember which version of Erlang was the most current when I started learning Elixir, but I do know that it was years before OTP 20, which fixed its string issues. Prior to that, Erlang didn't have very good string support for internationalization (I do a lot of Japanese language programming). Elixir, on the other hand, did. Otherwise, I may have gone with Erlang back then.
I like Erlang a lot, too. Both are great languages.
BiteCode_dev a day ago
If one need to get on Beam, is it better to start on Elixir or Gleam?
pdimitar a day ago
Elixir's ecosystem is much farther ahead than Gleam, so if you want to actually achieve stuff without pauses to fill the gaps yourself, then Elixir is the way to go.
And don't get me wrong, I love the idea of Gleam, a lot (Rust syntax, strong static typing, what's not to love?). But my PL early adopter days are over.
this_user a day ago
Because you love using Microsoft's shitty technologies, but also want to be completely unemployable?
pacoWebConsult a day ago
It's pretty baseless to claim that modern dotnet is inherently shitty. They've made tremendous strides in the dotnet core era.
F# making you unemployable is debateable, but I don't see what makes F# any less employable than most other FP languages. They have some niche applications that make it useful rarely, but when they're useful its a terrific tool for the job. F#'s ability to interop with the rest of the dotnet ecosystem positions it better than most functional languages for business usecases.
zem a day ago
I'm sure Microsoft has developed a lot of bad tech, but by and large their languages have been great. msvc c++ compiler as a possible exception, but f# in particular is excellent.
gwbas1c a day ago
I've spent my entire career, 22 years, primarily in C#.
I'm quite employable.
wiseowise a day ago
> Because you love using Microsoft's shitty technologies
If we go by the joke in gp, this is you.
tialaramex a day ago
RKFADU_UOFCCLEL a day ago
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 a day ago
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.
loxs a day ago
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 an hour ago
> 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 a day ago
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.
UK-Al05 7 hours ago
Less arduous memory management.
airstrike 4 hours ago
DeathArrow 2 hours ago
You get speed of development, productivity, lots of libraries. You get something that is easy to learn and understand.
airstrike an hour ago
fud101 a day ago
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 a day ago
I'm .NET dev and haven't touch a windows device since 2019. Work on Mac, deploy to Linux.
CharlieDigital a day ago
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 20 hours ago
> i can't bring myself to deal with Microsoft Windows and their tech
Even in a VM? Why not?
oguz-ismail a day ago
>whitespace is significant, like in Python
hard pass
110bpm a day ago
This isn't such a big issue in my experience. Auto-formatting helps a lot, the code needs to be just syntactically correct.
The default F# autoformatter is bundled/supported by VS Code, VS and Rider [0].
[0]: https://fsprojects.github.io/fantomas/docs/end-users/StyleGu...
int_19h a day ago
F# has both "lightweight" (indentation-based) and "verbose" syntax. If you don't like significant whitespace, you can just use the latter.
https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref...
sundarurfriend a day ago
That's an interesting idea and implementation.
I don't think being whitespace-significant is a "hard pass" dealbreaker, but as someone who's not a fan of it, I'd say this only goes a small way towards alleviating that - like most "choose your preferred syntax" designs. Even if you're a lone-wolf developer, you're gonna end up reading a lot of example code and other material that's in the ugly whitespace-sensitive style, given that:
> The verbose syntax is not as commonly used ... The default syntax is the lightweight syntax.
And most people in practice are not lone-wolf devs, and so the existence of this syntax helps them even less.
lunarlull 20 hours ago
You never touch python code either?
oguz-ismail 13 hours ago
not since they binned 2.7
voidUpdate a day ago
I was with it until I heard no braces :/
pjc50 a day ago
I have some good news for you about C#.
voidUpdate a day ago
BeetleB a day ago
fire_lake a day ago
Static typing removes the downside of whitespace.
Oh, and every language with line comments (so most of them) has significant whitespace.
AnimalMuppet a day ago
> Static typing removes the downside of whitespace.
How so?
> Oh, and every language with line comments (so most of them) has significant whitespace.
Technically true, but that's not what people mean by "significant whitespace" in this context. So you're being pedantic rather than saying anything meaningful.
But you made me think. The ultimate nightmare would be significant trailing whitespace - the spaces and/or tabs after all the visible characters change the meaning of the line.
Akronymus 2 hours ago
fire_lake 21 hours ago
fnord77 a day ago
> Trivia: F# is the language that made the pipeline operator (|>) popular.
laughs in clojure
nudpiedo a day ago
Same as many, I had wonderful experience with F# in the past, I would use it again if:
- fable would 100% detach from dotnet - keeps up yo the LLM rush, specially vibe coding on cursor
Last LLM experience it generated obsolete grammar (not much but a bit).
Such la gauges are key for vibe coding experience and modeling.