Fable 3: F# to JavaScript compiler
fable.io
fable.io
Elmish framework provided a nice MVU pattern for the U/I.
And the real icing on the cake was this Thoth.Elmish package which creates statically-typed proxy for your front-end to access your back-end API, more or less transparently. I was always certain that I would some day do something unorthodox causing its automated serialization/deserialization to fail in some difficult-to-troubleshoot way but no, that never happened and it all just worked transparently.
This was hands down the best automated-correctness-checking experience that I've ever had in any framework.
I really like F# as a language, but it's hard to give up the high quality tooling of VS Code + TypeScript + almost any NPM package w/ proper types.
Ended up using Typescript instead and it doesn't feel as clean.
This is my gripe exactly. If you gave me Svelte# and we'd be talking (my TS is pretty functional otherwise).
We’re using F# React on the front-end, Giraffe on the back-end.
DustyTables for Data Access.
It’s great - can recommend.
It’s a niche, but it exists and is growing.
If you want one and are willing to take a few compromises you’ll find one.
I find this a bit intriguing because the library support for linear algebra, probability and statistics is pretty slim both in .NET and OCaml. The latter has OWL, which is very cool, but it's mostly a 1-person project.
Do they develop all this support in house? For example, in insurance you may need things like Gumbel or Fréchet maximum likelihood estimators. That's not so easy to implement on your own, especially not without some linear algebra and optimization primitives available.
On the other hand, I love these languages, and I wish there was a strongly typed contender to Python, R or Julia. Whenever I develop a data-oriented application, it feels like I need to prototype in one language and in order to scale or develop the whole infrastructure, I need to switch to another language.
Julia has solved some of these problems, but I don't see a team implementing tons of business logic in a medium sized application using Julia.
https://www.quantconnect.com/blog/top-numerical-libraries-fo...
I guess a lot of the .NET ecosystem is like that. It's a shame, because MS has some open-source jewels like Z3 or Infer.NET.
But, the F# PM has recently given talks recognizing that they want to go into the space that Python is dominating, so it's a clear goal of the F# team (https://www.youtube.com/watch?v=_QnbV6CAWXc). I hope they're successful!
From the outside it always looks like an uphill battle for F#.
It would be great if F# finally gets its place across the .NET stack.
But even still - my app is sideloaded and never needed to care about .NET Native at all.
The official set of programming languages getting UWP support as part of Project Reunion.
I wouldn't confuse Project Reunion and the arbitrary Windows Store requirement that apps be compiled with .NET Native. A requirement that, frankly, is on borrowed time anyway and I can't envisage it surviving much longer. Once .NET 6 delivers Mono-style AOT support - .NET Native's sole remaining purpose will cease to exist. Not that modern hardware ever needed it. It was intended for Windows Phones.
If the choice facing us was a simple as you describe then, for example, we wouldn't have ended up building a UWP app in F# back in 2018, would we? Not everything is black and white nor zero sum.
UWP is still the future of Windows API, Reunion is only lifting it from the Windows kernel, and exposing the respective COM infrastructure on the Win32 side as well.
When I create applications for customers I don't select technologies that require me to place workarounds that might make them repent for having me there in first place.
Hence why as much as I like F#, it is never going to be an option for me, until it has a seat at the table of the official languages.
Apparently that isn't an issue in your case, so good luck with the endeavours.
UWP is the future of Windows - correct.
I'm not sure any significant part of UWP has ever been in the kernel per se.
It sounds like you're a consultant where taking risks on behalf of your customers, no matter how small or logical the risk, is obviously not part of your job description.
Your offerings of good luck appear to be disingenuous.
So if their IT goes down and the reason is that a risky loving consultant used unofficial workarounds, I rather not get unnecessary phone calls.
As for the wishing luck, I was being honest, take it as you wish.
I suspect you'll say "7 years is nothing" and maybe it is nothing. But it is still something. It is long enough that we made a couple bad framework/library dependency choices early on and to have learnt lessons from such mistakes.
By far the biggest technical challenge we've faced in that time is the .NET 5 migration - but even that might turn out to be a lot easier than I currently envisage.
Still no VS or Blend tooling support, no project templates and .NET Native requires workarounds with stuff that most corporate enterprise developers don't care to learn.
If you want to work in F# come up with your own OSS projects or champion it at work.
What sometimes leads to problems is F#’s record and discriminated union types.
Not sure how they are handled by EF Core.
Going back to plain SQL is just great. You know exactly what SQL gets executed. No Magic.
With DustyTables it’s also not too much boilerplate.
1. you need a dummy type[2] for empty parts of the union.
2. it still can't enforce exhaustive matching.
[1]: https://stu.dev/pattern-matching-fsharp-union-types-in-cshar...
[2]: Maybe () would work?
Saturn
Azure App Service
Fable
Elmish
Slightly off topic but it’s good to see that F# is finally getting some proper web love.
I have only done some toy projects on it so far, but am really digging it.
* Suave
* AWS
* Fable
* React
SAFR? It's great, but missing a snazzy acronym.
All our new code is in F#, we started off from a C# codebase, so that made the transition somewhat manageable, as new F# code can be directly called from C#, and vice versa (still took over 2 years). All new frontend apps are also being written in F# (using Fable), as of 6 months back, migrating away from TypeScript, this forces everyone into a "design your model first, and well" paradigm. We've written quite a bit of code to blur the lines between traditional backend and frontend development roles, so what we have now are:
- product engineers (who write application logic on both frontend and backend to serve business needs)
- platform & framework engineers (who write the underlying persistence/serialization/versioning/frontend-backend-sync websocket/load balancing/IDE extensions/deployment etc)
- component designers who focus on visuals
Platform/framework engineers try to encapsulate as much magic as possible into computation expressions (F#'s monads), so product engineers can focus simply on writing out business intent, with readability given very high priority. We also make ample use of quotations to do some cool tricks (like predict the future states some type can take, based on current state + available transitions).
Our code written in F# has an order of magnitude fewer bugs when it makes it to production, given the amount of thought we pour in modelling the problem domain accurately, and thanks to functional programming itself. They're also more amenable to business requirements changing, simply because they've been modelled well to start with. Nothing that can't be achieved in other languages, but with F#, this happens more naturally.
Almost everyone in our team has learnt F# on the job, and overall, everyone's experience has been extremely positive. There's a bit of difficulty in the first 2-3 months, as junior devs get introduced to functional thinking, but if you've generally being doing functional programming, this is just about learning new syntax, tooling and F#'s choice of operator naming (map/bind/pick/collect/choose/..). Typically, based on prior experience, we ask newcomers to spend two weeks to a month, solving the first 100 problems on Project Euler in F#, without using the mutable keyword, and we assign a mentor to point out best practices and review their code.
The hiring pool for F# devs is much smaller than the regular applicant pool, but if a candidate shows genuine interest in F#, they are usually 10x more likely get through our interview process. If they've discovered F#, it means they find something lacking with mainstream languages, so they're likely to have many years of experience under their belt, and they've found a way to grow. That said, we don't restrict our hiring to simply F# devs.
For more info about us, see chaldal.tech (YC/S15).
> We also make ample use of quotations to do some cool tricks (like predict the future states some type can take, based on current state + available transitions).
You can do similar things with other Ocaml or Lispy Langs, depending on how you want to do it. All you need is a function that returns possibleTypeTransitions for givenType(type, enclosedLexeme, type.validTransitions). A gradually typed lang sitting in top of a prototype-based blob also makes this easy to do (see typescript) in-codo.
See also MacKay (RIP)'s classic book: http://www.inference.org.uk/itprnn/book.pdf
let transition (state: State) (action: Action) : State option =
match (state, action) with
| (StateA, ActionA) -> Some StateB
| (StateA, ActionB) -> Some StateC
| (StateB, ActionA) -> Some StateB
| _ -> None
If you get the quoted representation of the transition function, it can be visualized as a tree data structure (like code-as-data in LISP). You can analyze that tree to understand that if current state is StateB, only ActionA can be applied on it.Couple this with another realization: "Any sufficiently complicated model class contains an ad hoc, informally specified, bug-ridden, slow implementation of half of a state machine." (not sure where I read this quote).
This means all the entity framework/ORM crap work that we do can actually be neatly represented as transforms on a F# state machine, which suddenly makes the application more powerful if you give it this structure.
We use this technique to auto-generate admin panels.
Can’t tell you where you read it, of course, but believe it originates from Braithwaite/raganwald:
Also, I really like this post: https://fsharpforfunandprofit.com/posts/low-risk-ways-to-use...
Trying to figure out how to map to an overloaded C# callback (maybe hidden in an *.extension doc!) has wasted hours of my time.
F# (the ml family in general) is my favorite language right now but, man, the .net APIs are rough.
Lacking the same UX I’m used to in Node, Ruby, and Elixir.
Example here is the String doc[1]. Way down you see all the methods. Some of the methods have overloads (multiple variants). Pretty straightforward here. (E.g. `"mystring".Contains("ring")`)
Where it gets more verbose and finicky is when the API takes a C# callback. Even more complex is if it’s asynchronous so it takes a C# callback as a Task.
An example being the `.Use` method for defining server middleware.[2]
To see how it’s done, here’s a gist I found.[3] Notice how the function for requestHandler is verbosely annotated with Func<> and RequestDelegate, etc.
Luckily this isn’t the norm, most APIs are less complicated. Even so, you write a wrapper (abstraction) around that complexity and only look at your wrapper. Which is why someone in this thread said to leave them in a dark corner.
[1]: https://docs.microsoft.com/en-us/dotnet/api/system.string?vi...
[2]: https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnet...
[3]: https://gist.github.com/kspeakman/7870a75283f6942dd96ff34a03...
https://www.nuget.org/packages/TaskBuilder.fs/ https://github.com/rspeele/TaskBuilder.fs
I'm really having fun experimenting with F# for my API server, but I hesitate to use it on the front end.
I just now dumped a 350KB JQuery.d.ts file into it, and sure enough it spit out F#, but confirming how well it works overall would take a lot longer to ascertain.
Always seemed to me like having a really robust tool for this purpose (or else, just a rich direct Fable-typing selection) would be a huge boon for the whole Fable ecosystem.
Is the only difference the ecosystem around the toolchains?
F# was heavily inspired by OCaml, it was originally intended as "What would OCaml look like running on .NET?" so the languages themselves share a lot of similarities.
ReasonML pros:
- ReasonML compilation times were much faster than Fable 2, but Fable compile times weren't bad. OCaml is ridiculously fast.
- OCaml has an interesting module system that's missing from F#.
- The toolchain feels a lot more lightweight than the whole .NET toolchain.
Fable pros: - I found interop with JS and OOP stuff much easier in Fable than in ReasonML
- Fable has a tool for converting TypeScript definitions to Fable definitions - though it hasn't always worked for me for more complex type definitions
- I prefer F#'s whitespace sensitive syntax over OCaml, but that's just personal preference
- F# type providers are pretty cool
- F# has an interactive mode, and you can write standalone scripts (eg. for devops)
- If you want to write a web backend in the same language, F# on .NET is much more mature in the web space than OCaml.Computation expressions are like do-notation and list comprehensions in one feature. Now that I have tried them, I don't want to go back to a language without!
What's really cool is that things like ```async function *``` from JS can be implemented as libraries in F#.
- compare their experience with ReasonML since they both have the same OcaML pedigree
- offer any perspectives on efficiencies of various constructs? For example, do things like seq add additional complexity or are about as efficient as for loops?
- discuss the output size .. by virtue of using .net libraries versus javascript builtins?
Dismissive maintainers indeed!
Would I recommend others to throw away React or similar to use it? Maybe not, but it's mostly painless to use day-to-day.
https://news.ycombinator.com/item?id=22237578 (I wrote this exact comment about you 10 months ago on another F# + JS submission)
If this is going to be your hobby horse, why not put some effort into it beyond "lol sux"?
The one true way (his book is also very good)
Don't even get me started on the total farce that was the Fable: The Journey was. Cool concept, poor implementation.
F#’s async workflows are supported.
Not sure how this is implemented behind the covers - I guess it get’s compiled to JS promises.
Good point. I guess I meant parallelism instead.
https://stackoverflow.com/questions/1050222/what-is-the-diff...
I think it can still be archived with web workers.
But honestly, its own async model is great - arguably better than TPL for business systems. It sacrifices a little top-end performance/power and in return you get a supremely clean abstraction.
I used to hear that quite often - not so much in recent years, if I think about it, but that may be by chance. I think it is what I would say.
I'm sure someone must use it but it's not at all common
Update: the issue is tagged await-csharp-alignment, which is probably the relevant status.