raphinou
Lanayx
For reference, F# slack is already dead, community has moved to Discord https://discord.com/invite/fsharp-196693847965696000
kqr
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
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
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
What about libraries though? They might force you to use certain monads rather than IO?
kqr
The libraries I use either have, or at least allow, IO at the base of their transformer stacks, so any IO action is a liftIO away.
ninetyninenine
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
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
> 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.
This is a good observation.
As someone who writes a lot of Lisp, I'm inclined to agree as the amount of people that have never written any Lisp yet immediately reject it over syntax over fears that it somehow hampers development is a (to me) surprisingly large number of people.
If I recall correctly, one of the motivating factors for Rescript was to reduce the perceived/real distance between Reason and JS in order to attract more JS devs, as Reason was so heavily associated with OCaml.
mike1o1
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
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
This is a really minor point, but "strongly typed" and "statically typed" are not interchangeable terms. In the context of your comments here, you are exclusively interested in the static nature of the type system, rather than anything about the "strength" of it (which is something totally different and inconsistently defined).
tasuki
These days there's Gleam[0], as a strongly typed alternative for the BEAM virtual machine. Of all the languages I haven't used yet, it seems to hit the safe + minimalistic + productive sweet spot the best. (Yes the C-inspired syntax is slightly off-putting, but syntax is the least important aspect of a language.)
[0]: https://gleam.run/
asadbeksindar
Hey, thank you for sharing your app's source code. I'll definitely check it out, I was really looking for such apps on F# open source projects!
breadwinner
Apache Spark, Delta Lake are written Scala. Being JVM based, it has a large ecosystem. Scala seems like a better choice than F#.
raphinou
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
I agree with you. I tried Scala for weeks and found it far too complex. Every line I wrote, I felt there were 5 different ways of doing it and I didn't know if I was choosing the right one. Scala tries to be too many things at once imo.
hurril
It runs on .NET, for god's sake. This is not a small platform.
flakiness
Is F# easier to learn than Scala? (I know a bit of Scala (in the old 2.x days) but have no knowledge of F#.)
apwell23
i've used scala for over 8 yrs everyday and i agree with your assessment.
Even intellij has no idea sometimes about what the hell is going on. It throws up compile errors when there none.
michaelcampbell
Is Frege still being developed?
innocentoldguy
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
> Every code base I've worked on in Scala has ended up being a hodgepodge of both
Is there something about that that has bothered you? Working in Scala codebases, I've found the best ones to work in are the ones that embrace Scala's multiparadigm nature. When programmers try to solve every problem with OO, they end up adding more and more layers to get the job done. When programmers try to solve every problem with FP, they end up resorting to sophisticated techniques that are unapproachable for other engineers. I think the simple parts of OO and the simple parts of FP go much, much further together than simple OO or simple FP can go by themselves. Have you seen something different?
raphinou
Elixir getting a strong type system is interesting, but watch out for gleam though
But they still miss the computation expressions, which open interesting possibilities like https://github.com/CaptnCodr/Fli and https://github.com/fsprojects/FsHttp
throw234234234
Evaluated F# vs Clojure. Speed of certain algorithms just lacked for me. Value types particularly in tail recursive stacks shines in F# compared to the JVM in general. As usual YMMV
michaelcampbell
Isn't Clojure similarly (or even moreso) multiparadigm?
bozhidar
Great story! Thanks for sharing it!
rockyj
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
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
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
It is extremely niche outside of this bubble.
DeathArrow
Just look at the job market. There are far more jobs for Go programmers and Go isn't particularly huge.
Compared with C/C++, Java, C#, Javascript, Python, Typescript, PHP, all the rest can be considered niche.
tester756
>" 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
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
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
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
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
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
> 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
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.
protonbob
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
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).
gdfsfs8895
[dead]
darksaints
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
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
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
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
C++ I have worked only a little with it, more so with C, but AFAIK order of files does kind-of matter, so at least declarations need to be present in each file upfront before use.
C# has a multi-pass compiler so that it can compile and link the components from multiple files, without need of placeholder declarations, regardless of the order the symbols appear in the files.
F# has a single pass compiler, which keeps the compiler implementation simpler, but the file, and symbol definition order does matter that way. This is totally intentional, this is supposed to make the codebase more straightforward, with which I personally agree with. This avoids the need for declarations and centralization of them, the includes all the baggage that comes with that approach, and all the complexity C# has. I have rarely found a limiting factor, though there are some cases when it can be a bit inconvenient, for me the application setup/composition (~DI, but I prefer more static approach in F#) needed some cumbersome refactoring in some cases (have only vague memories by now, and yes, I know co-recursive types exists)
I really like F#, but rarely have to opportunity to work in it.
Lyngbakr
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
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
(writing all the below while being aware you likely know much more about OCaml than I do...!)
Possibly `eval $(opam env)` is something that should just go in your ~/.zshrc
The OCaml folks have done some work recently to improve the onboarding documentation, which I think is going in a positive direction
e.g. https://ocaml.org/docs/installing-ocaml (the eval as a one-off post install command)
And then guiding people to use 'switches' https://ocaml.org/docs/opam-switch-introduction, which I totally missed when I started with the language.
> Local switches are automatically selected based on the current working directory.
johnisgood
The only issues I've had with OCaml's build system is using "ocamlopt", "ocamlbuild", "ocamlfind" manually, but this was solved by OASIS and now Dune. I don't need to think about it. It automatically compiles when I save the file in Emacs. Very easy to set it up (one time setup).
germandiago
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
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
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
> 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
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
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
I would call .NET build system excellent.
fodkodrasz
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.
jayd16
Whats pretty interesting is how outdated opinions of .NET are so sticky. Are we talking about what javascript was like 10-15 years ago?
I guess Microsoft could really make some headway if they got more folks to try it today.
pimbrouwers
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
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
> 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
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
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
Hi Isaac ;) Of course you can train people. But in my experience they take a lot longer to learn than you suggest.
z5h
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
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
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
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
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
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
> with gradual typing
Isn't gradual typing widely understood to mean "gradual between static and dynamic", which F# certainly isn't?
foretop_yardarm
Thanks for your work on falco, it’s a really great library.
DeathArrow
>- there are very few opportunities to use it professionally
- hiring devs can be challenging
Those drawbacks are huge, IMO.
lihaoyi
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
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
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
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
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
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
So, there is a gazillion ways to do things and the community didn't settle on one? I don't find that very attractive when trying to learn a new language.
tasuki
Very good summary, thank you! I've mostly stopped writing Scala, but it's still close to my heart.
null
eknkc
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
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
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
I think LINQ is inspired by SQL. You can do whatever you can with SQL, it's just that the data source might differ IEnumerable with some in memory data, IQueryable with some DB. Or you can use async enumerable and your data source can be whatever web API or protocol.
psychoslave
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
Ruby is dynamically typed, which makes "fluent" API design that much easier at the cost of maintainability elsewhere. If you want to compare apples to apples, you need to compare F# to other statically typed languages.
bob1029
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
I wouldn't say "all" - C# doesn't have discriminated unions yet, which is kind of a big one, especially when you're also looking at pattern matching. A
UK-Al05
A language is just as much about what it can't do, then what it can do.
guhidalg
I don't know if there's a name for it but essentially F# is where the language designers can push the boundaries and try extremely new things that 99% of users will not want or need, but eventually some of them are such good ideas that they feed back into C#.
Maybe that's just research, and I'm glad that Microsoft hasn't killed F# (I do work there, but I don't write F# at work.)
klysm
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
Yeah, I hit the problem that there isn't a null-type equivalent of Select() for Action<T>, nor is there a IEnumerable.ForEach (controversial), so that's a bit of a hack. But I wanted to make it as close to the original example as possible.
bob1029
> There’s no reason to do ToList there
In this case, I would move it to the very end if we are concerned about the underlying data shifting when the collection is actually enumerated.
Forgetting to materialize LINQ results can cause a lot of trouble, oftentimes in ways that happily evade detection while a debugger is attached.
DeathArrow
Yes, ForEach isn't idiomatic but he could use Select instead.
kkukshtel
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
I did try that initially and got
<source>(5,1): error CS9176: There is no target type for the collection expression.
.. which I took to mean that, because .Select is an extension method on IEnumerable, the engine was unable to infer whether the collection should be a list, array, or some other type of collection.It seems reasonable to have it default to Array if it's ambiguous, maybe there's a downside I'm not aware of.
voidUpdate
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
That could be shortened to
names.ForEach(name=>Console.WriteLine($"Hello, {name}! Enjoy your C#"));
gibibit
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
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
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
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
"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
I'm pretty sure that there's more production code written in F# than in all those other three combined.
psychoslave
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
Clipper is old. It's dBase/xBase/FoxPro, pre-SQL DBMSs.
DeathArrow
If we consider number of jobs, it's probably on par with Rust.
reverseblade2
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
The navbar takes up half my screen on an iPhone 13 mini :/
kingkongjaffa
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
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
> 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
you are not supposed to do oop in f#
7thaccount
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
100% this, I spent many months going through the most recent books on F# including one which the latest version was only released last year I think.
They all seem to try and shield you from the fact that you are much better placed if coming from C# (which everyone seems to refer to as .net these days) and have a solid understanding of the .net class library.
All the main web frameworks sit on top of asp.net and pretty much all official documentation for that is in c#
Such a shame because I learnt so much about types from trying to crack f# for real world application. fsharpforfunandprofit taught me heaps which I apply to other languages, but I don't want to become a c# developer which comes with all the years of changing best practices to be able to really be productive in f#.
Sorry if I am coming across as bitter but I just can't see learning f# in isolation from c# which is an absolute shame.
hajile
F# depends heavily on existing C# libraries and those are all OOP.
smoothdeveloper
One way to look at it, but consuming OOP libraries doesn't turn code into OOP.
Also, FSharp.Core (which most F# code leans heavily on) is not OOP at all.
F# promotes object programming, doesn't proscribe mutability, encourages function and data approach.
It offers simple access to the different paradigms, with some opinionated choices (e.g. preventing leaning on OOP beyond an arbitrary stretch, like no "protected", only explicit interface implementation, etc.).
genter
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
FP and classes are not mutually exclusive
ninalanyon
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
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
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...
null
Hojojo
Wow, that sounds awesome. I'm jealous.
a-french-anon
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 ";;"!
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/