A Brief F# Exploration
notes.srid.ca
notes.srid.ca
I also dislike the default workflow for dealing with Nuget forks. I switched to Paket for dependency management which makes this much simpler. https://fsprojects.github.io/Paket/
Many of which did have a REPL.
Also the dynamic language runtime originally designed for Iron languages, Python and Ruby, precedes F#.
This is already bearing fruit in the latest preview: https://devblogs.microsoft.com/dotnet/announcing-net-6-previ...
I also saw this lovely update for Xamarin.Forms users https://twitter.com/drasticactionSA/status/13802626828724428...
in frontend, bucklescript changes too quickly. js of ocaml is hard to use. good luck if you want to trim the code size.
It’s super easy to mix C# and F# code in the same project and it works out of the box.
This allows you, if you want it, to write your domain code in F# and your technical code in C#.
F# is low risk to adopt compared to OCaml. F# is the functional language pick that won’t get you fired.
The tooling is poor in general, the interop is questionable at best. One example is `Option a` in F# becomes `FSharpOption<A>` in C#, with `None` being `null` - breaking all of the type-safety of the union-type. It isn't seamless in the way some might have you believe. The standard answer is build a wrapper to expose F# to C#, which is ok, but is an extra level of indirection and complexity that shouldn't be needed (if indeed the idea is to have seamless interop).
I developed language-ext [1] to bridge the divide, but in the end there isn't a strong enough reason to write F# all the time in the .NET sphere. It is compromised by an ecosystem where C# is dominant. That includes the framework libraries and even the limitations of the type-system in F# (no higher kinds for example). There's no real reason for F#, other than a nicer syntax, it doesn't have a killer USP like Haskell (purity) or Erlang (concurrency).
If it wasn't in C#'s shadow, and it was able to run free, and without compromise, there could be a compelling narrative - but what we're doing now is moving to PureScript for our front-end, and Haskell for microservices where we need the USP of Haskell (purity and strict domain modelling).
For my shop, the AD module was an obstacle until v7. Many Azure-related modules still seem to be 5.1 only.
Because -- you know -- in the 2020s there are only web apps and mobile apps. There are no other types of "applications". That unnecessarily long word only exists in dead tree dictionaries like Oxford, and is used by old people that still cling to their "personal computers" of yesteryear. So of course, .NET Core was made only for web apps, with a hint that mobile apps might one day work also. Microsoft will say otherwise, of course, but in practice 100% of the decisions were to ship an MVP that can be used to create a web application. All the doco was for web apps. All of the samples were for web apps. Whenever there was a decision to be made, they made it with web apps in mind.
This has made some things impossible, especially related to actually loading dynamic link libraries (DLLs) dynamically, which despite the "dynamic" in the name is surprisingly problematic in .NET Core.
It really wants you to ship a monolithic, statically linked app. Anything else is just a nightmare of compatibility shims and flags that ought to be at the DLL level but are actually set (once only) at the EXE-level.
This makes PowerShell Core modules very sensitive to the exact version of .NET Core used to compile PowerShell itself, contrary to how the old PowerShell used to work, where you could upgrade the system framework to enable the loading of a newer module built against that framework.
Similarly, if there is another module that pulls in something with compatibility shims (or not), then that can break your module in weird and wonderful ways.
I tried to write a .NET Core module for PowerShell core several times, and every time I got bogged down in reams of inscrutable internal framework errors that had 2-3 hits maximum in Google, all from other people complaining about PowerShell development having being broken.
Any language developed on dotnet platform will always be in C#'s shadow. F# is much nicer to write than C#(for now), if you need to develop on dotnet.
What are my options?
- PureScript on web and Node.js
Can use NPM packages! Node.js as a run-time lacks features like shared memory across threads. PureScript is still too early IMO.
- Scala on JVM and web using Scala.js
Not a bad option, although the language is very complex. More towards the OOP end than the ML end in the spectrum of language design. JVM can be a good or a bad thing, depending on what you are doing.
- F# on .NET Core and web using Fable
Simple functional language with access to the .NET ecosystem. ASP.NET has great performance. Access to NPM packages on web. Lacks some advanced type-system features in Haskell, OCaml and Scala. However, the community has a pragmatic focus as a result.
- OCaml and ReasonML
ReasonML has limited backing from Facebook. OCaml has support from a few financial institutions (e.g. Jane Street) but it's not on the same level as what a big tech company could provide. Tiny (but high quality) community and ecosystem. OCaml has great single-threaded performance but mult-threading is not quite ready. Already small community split by compiler extensions and standard libraries.
- Haskell and GHCJS
Again, tiny community and ecosystem. Beautiful language, but lazy evaluation has bit me too many times. Steep learning curve since newcomers cannot fall-back to OOP and imperative code.
- Elm
Tiny ecosystem, tied to Node.js (see PureScript). Interop story with NPM modules is worse than PureScript.
For me, F# is the clear winner.
If you aren't particularly interested in functional programming - maybe you just use some delegates here and there - then C# is a fine choice. Otherwise, C# quickly becomes awkward compared to F#. Besides, C# to JS options are not as mature as Fable.
I wonder what is easier for a strong OOP developer to learn, Lisp or ML?
ML, depending on the flavour gets pretty how one combines functors, aka generic modules, which is similar to component based programming like COM, or just plain objects as in OCaml.
Now the immutability isn't as hard to adapt to as one may think.
Also I bet that The Art of Metaobject Protocol reference implementation can be ported into Clojure without major issues.
https://clojuredocs.org/clojure.core/defprotocol
"A protocol is a named set of named methods and their signatures"
Such protocols are not a language feature of CLOS.
AMOP describes a 'Metaobject Protocol' (MOP) and has a tiny example implementation (called Closette). This is entirely different from what the 'protocols' feature does in Clojure. A 'protocol' in AMOP is informal.
What AMOP actually describes with its MOP, is a meta-level of meta-classes and generic functions, which implement large parts of CLOS itself. Such the classes, generic functions, methods, slot descriptors, etc. are CLOS objects themselves.
Clojure supports a form of multiple dispatch, but the dispatch mechanism is also very different from CLOS - for example it uses a dispatch method per generic function, selects one method and has no idea of a next method. CLOS for example uses a built-in dispatch mechanism, multiple class-based dispatch hierarchies for multiple arguments, using a set of methods which are selected based on the class hierarchy.
https://clojure.org/about/runtime_polymorphism
Typically it is not a good idea if Clojure uses a name for a feature, to generally think that this is similar to a feature with a similar name in Common Lisp -> 'protocols' and 'meta-object protocol' are two very different things.
Porting the CLOS MOP to Clojure would be possible, when one first implements CLOS in Clojure. Otherwise it makes very little sense, since Clojure does not by default support the (older) view of object-oriented programming of CLOS. Something which the Clojure designer thought of a feature: getting rid of things like mutable objects, class based inheritance, class-based OO, etc.
Great library by the way thanks for making it!
However given the whole Project Reunion and uncertainity how both worlds are supposed to be merged, maybe it isn't such a big deal.
Ah and don't expect Code Generators to ever support F#.
What sort of Code Generators are we talking?
I ask because I have a very early alpha project that does F# code generation using Fantomas. Apart from an (uninvestigated) slightly higher startup time than I hoped for, it seems fine.
https://devblogs.microsoft.com/dotnet/introducing-c-source-g...
The main goal is for them to be the .NET version of Java's annotation processors and thus allow many libraries to replace their reflection code with compile time code generation.
I followed the link to the F# suggestions and found
https://github.com/fsharp/fslang-suggestions/issues/864
It seems like there is interest but with a "let’s wait and see what happens with C#" kind of approach. I’ll admit it looks far off, but there appears to be interest.
I’m certainly not expecting them, and for my purposes F# provides more than enough anyway. I am nonetheless interested: why do you think they will never come to F#?
Until now, all the F# related tooling tends to be done by a mix of the tiny MS team and FOSS community, it is not the full steam rolling engine that C# and VB get.
In the long term there is far less chance that the INRIA drop OCaml than microsoft drop F#.
In some ways, on the other hand F# has active patterns and type providers, which are quite magical.
PureScript does have an Erlang backend as well.
My understanding is F# relies on a JIT just as Node (V8) does. Are either really native? Are both?
FAFAIK Node doesn't compile to an intermediate language, it either compiles to minimzed (lets-just-remove-all-whitespace) Javascript, or it generates a native binary.