Fable is a compiler that brings F# into the JavaScript ecosystem
fable.io
fable.io
It doesn't try to hide the fact that when you write a Fable program, you're fundamentally in the JS ecosystem. This can be a bit of a shift if you're used to doing stuff in .NET, but it means that everything will more or less work with your code.
It also comes with a few tools/utilities to ease the F#-JS bridge you're on.
So you can call any .NET library?
In practice you occasionally find something that doesn't quite work, for the most part things related to IO and the TPL but I occasionally run into some more niche functionality with Date & time for example.
You can use most of the core F# library and some non fable centric libraries (e.g. FSharp.UMX of FSToolkit.ErrorHandling) work just fine.
I find it mostly a non issue, as any IO you want to go through the browser API instead or it's not supported. It didn't take take long at all to easily slip into the "I'm in the browser now" mindset.
I like React and I like F#. But I never understand this kind of marketing. It's not that I want things optimized for pain. But I guess I'm just most interested in the technical choices and actual performance in the domain over my own happiness?
Unless you meant something else there?
So I'd rather marketing just say exactly what it's direct goals are rather than indirect ones like happiness.
> Since the F# transpiles into JS at runtime it's really no different than, say, TS in terms of performance concerns.
But as a particular point, this is hard to believe. TS tries to have no (or a minimal) runtime component whereas F# definitely must have a major runtime component.
Besides his numerous repos, the Elmish book [1] is really awesome.
These things are bizarre when you think about the tech stack they lead to, but undeniably still really useful in our unfortunate real world. I think of F# as 'the pragmatist's functional programming language', and projects like this follow that mindset.
My sense is that the root cause of a lot of it is missing features in the Java language itself. There are a lot of cases where in C# I'd have used an extension method, or been able to lean more heavily on generic programming or Expression<T>, but, since Java has no good equivalents of these things, instead I have to break out a design pattern to accomplish the same task.
And, once you've cracked that seal, it's sort of an, "In for a penny, in for a pound," type situation. Next thing I know, I'm neck deep in it, and I don't even know how I got there.
It's true that, in a single dispatch language, I sometimes need to use the visitor pattern. And the visitor pattern is a little bit annoying to implement, it's true. But the implication of that Norvig quote is that every single language should implement multiple dispatch, and I simply cannot agree with that. And I suspect that a lot of people who like to invoke that sentiment would not prove to have the courage of their convictions when presented with a situation where Haskell needs a design pattern (sorry, "idiom") in order to work around the fact that it doesn't have dynamic dispatch at all, multiple or otherwise.
In general, it's OK for languages to be small and focused, or even to be large and multiparadigm but still draw the line at adding some features. That's not my criticism of Java. My criticism of Java is more along the lines of, Java's a kitchen sink language, and there's nothing wrong (aside from perhaps aesthetics) with being a kitchen sink language, but there are other kitchen sink languages that did a better job of cramming more random crap in more cleanly.
The interest has always been consistent, it's just not vocal.
Looks like somewhat of an increase but a very spiky baseline.
https://hn-trends.eliot-jones.com/Home/Trend?id=f%23&allword...
I haven't run into any real problems as a result but it does make me nervous.
There are those who would argue that making an incompatibility between the database schema and the code that interacts with it a compile-time error instead of a run-time error is a huge win for software quality.
I suppose there are situations where you simply can't have access to a database that mimics the structure of the production database during development. In which case, the SQL provider is definitely not the right tool for the job. But it might be worth looking into ways to change how you do things in order to make it the right tool for the job. A SQL database with an unpredictable schema makes me much more nervous.
That's why you don't normally compile against the production database. You version control the database schema and use it to create a local database to compile against. This way you can also test potential future migrations using branches.
Compiling against the production database should be done separately, as a kind of free integration test (usually in CI).
Just one of the many reasons I find myself more and more excited by F#.
(Disclaimer that I'm not talking about compiling runtime-less languages for different platforms)
It just seems like it's going to be a very leaky abstraction, like there will be tons of corner cases where some behavior isn't exactly the same and other behavior isn't quite possible, which will cause libraries and in-house code alike to break in weird ways. I know that ClojureScript, for example, has several caveats relative to Clojure; and most of these translators are not nearly as mainstream (and so don't get nearly as much maintenance attention) as ClojureScript does. And then there's the messy question of interacting with the host system, dropping down into the host language for certain things, etc.
I haven't really worked with these kinds of systems so I may be way off, but from the outside it seems like a huge increase in complexity just so you get to stay in a familiar language
In other words, the language designers and users are already used to understanding corner cases and integrations into ecosystems that are different.
Still- I have to wonder about things like concurrency, which is perhaps the most obvious limitation of targeting the JS runtime
1: https://fable.io/docs/dotnet/compatibility.html#Caveats-II
There’s a function that Fable provides to turn a promise into an async, so mix and match isn’t a huge challenge anyway.
- F# has some significant advantages over JavaScript (and TypeScript).
We had issues with Dates. Implementing a custom 'ZonedDateTime' type with native implementations for both target platforms (JS and .NET) was straight forward.
Other than that there are a few gotchas when doing 'advanced' stuff:
- Fable does not support 'Array2D', 'Array3D', ... - Fable allows the use of ints but you have to know that at runtime they all are floats. - Fable does not support FSharp Quotations. - Fable does not support the full reflection API.
More here: https://fable.io/docs/dotnet/compatibility.html
Would definitely recommend F# for both backend and frontend. It's been a joy.
More broadly they aren't sure whether causing "libraries and in-house code alike to break in weird ways" on different hosts is a bad thing (some folks would probably take issue with the word "break").
On the whole however these projects can go very well. I've seen e.g. ScalaJS and Scala backend projects work very well. They're a lot less leaky than you would think. The vast majority of code just works. In particular, there are clean lines between what is supported by the abstraction and what isn't, and the latter doesn't affect the former, so in that sense the abstraction is pretty tight and not leaky. And the major win isn't so much the familiar language part as it is the ability to share code and definitions. It's really powerful to change a line somewhere deep in your backend and have all the places you need to make a change all the way out to the frontend UI automatically laid out for you.
That said the big misconception, and where the abstraction is incomplete if not leaky, is that these languages allow you to disregard the runtimes of secondary targets. No compile-to-JS language I know of has successfully done away with the need to understand the HTML/CSS/Javascript stack. And that indeed is extra complexity that should give pause to developers.
But RE "cause libraries and in-house code alike to break in weird ways" generally does not seem to be the case for these compile-to-JS languages.
In my experience you can achieve the same functionalities with a lot less complexity in Fable + Feliz than the equivalent typescript stack.
As to Fable.. I would want to use it on Vuejs perhaps if I can't do blazor, but also with something like mobx and NOT Elmish. I despise redux and it just looks gross. I want the Mobx "magic" for this boring view update stuff.
If F# is to be successful, I think more attention needs to be made to build abstractions on .net APIs.
If for whatever reason Suave is not fast enough, Giraffe can be fine tuned. However, it also exposes much of the underlying ASP.NET stuff.
I love the website for Wiz though!
Would challenge the notion of immutability or extensibility being a primary motive for using a library. Would like to see UX (DX more specifically) start to take more of a front seat in F#, since its one of the more neglected parameters of success in the ecosystem. Extensibility can be added, UX is more difficult to retroactively account for.
If Wiz only influences other libraries to become simpler for new users then I will consider it a success.
I just want more eng teams to use F# or Ocaml without having to justify why you aren't using python/node.js.
However, if you translated the Wiz examples to Suave, would they be any more difficult to read?
I think the biggest issue is Suave’s docs etc.
Seems like a neat project.
Similarly, Common Lisp has something called parenscript which compiles a lispy syntax to js but e.g. uses JavaScript arrays for its lists (so you don’t have a cons function).
For shared code it can be wise to maintain tests that can run on both .NET and Node.js.