I don't know how much of this is the F# team's fault, but F# the 'eco-system' feels like it's going backwards at the moment.
As in physics, it's all relative. .NET has been moving so quickly lately that the F# team (from my outside-looking-in view) does not have the resources to keep up. You can see that by how stretched thin they are on GitHub issues. I'd imagine things will eventually stabilize once .NET Core settles in, but that'll be a few years.
But you are right, the tradeoff always seems to be "do I want to struggle and learn" or "do I just want to get things done."
If you're waiting for Microsoft to give exactly equal resources to both C# and F#, you'll be waiting forever. Just like you'll be waiting for equal resources given to Visual Basic, TypeScript, PowerShell, VBA...
Equal splits never happen in a competitive situation. 60/40 splits are much more common, but here in this case, we have many first-party languages, so you'd expect a more complicated split, just as we see now.
> .NET Core 2.0 is in preview and there is ZERO support for F# with .NET Core in Visual Studio 2017
That's coming in the next update. (https://blogs.msdn.microsoft.com/visualstudio/2017/05/10/upd...) You've been able to run F# in .NET Core in preview form going back to the 1.1 series.
My opinion is that .NET Core is the real bag of hurt here, not F#. Stop sticking your hand in that blender. Use Mono and open source F# until .NET Core stops changing the world on each release.
> VSCode is no Visual Studio
And neither one is Vim.
Are we really going to have another editor war? :)
F# suffers from an overabundance of "getting started" tutorials that focus only on the language and syntax. I get that F# is likely to be a lot of peoples' first introduction to a functional language, so that makes sense, but this one doesn't even tell you how to run the code it's showing you.
The hardest part about learning any new language isn't learning the syntax or core concepts, it's understanding the mechanics of actually getting things done - grokking the developer workflow, getting comfortable in an editing environment, building and deploying, troubleshooting and debugging, writing idiomatic code, learning about common libraries and tools, etc.
I just found http://fsprojects.github.io/ProjectScaffold/structure.html, which is a good example of the kind of thing I'm interested in (ProjectScaffold in general, but that page in particular, which actually explains what everything in the project structure is for).
This link may help you,
It's pretty awesome
Yes. Your standard OOP features like inheriting from C# classes, implementing interfaces, etc are supported natively in F#. The main hassle in being C#-compatible is exposing an external OOP api with only .NET types and interfaces instead of standard F# types. This means, for example, exposing `seq` (`IEnumerable`) instead of `list` (`Microsoft.FSharp.Collections.List`) or using the struct-tuple construct in F# 4.1 so C# 7 can access it.
> good samples of real life application code
No personal recommendations but have you seen https://github.com/fsprojects/awesome-fsharp
Well, yes and no. You definitely can do this, and for some applications it's worth it, but often the overhead at the API level will make you cringe.
APIs designed for C# are very different than APIs designed for F#, to account for partial application of functions, sum-types, non-nullability, immutability and value-like behavior by default from F# types, and also to make good use of F#'s type inference. Also, given stuff like the |> operator, making "fluent" APIs looks very different.
Using APIs made explictly for F# from the side of C# is somewhere between enormously annoying and de-facto impossible. The other way 'round, it's just massively annoying, as you lose many advantages of F#, and the code will not be much more compact as if you would write it from C#.
Pain-points in practice are around F# functions vs. C# methods and delegates, async/await vs. async-expressions, code quotations vs. Linq expressions, etc.
To be productive in F#, you want your API small and primitive, and stay within the language for the rest. If this is possible, go for it; if not, evaluate.
A final tip: Porting a big block from C# to F# is much less work than it sounds, and opens the door to refactoring that part into something sensible.
If there were a ton of F# libraries that showed how to create functional APIs people could learn from them by using them the same way a lot people learn OOP by using APIs.
As it is now the only way to get into F# is to have a group who really wants to do it and learn. Otherwise it's just an uphill battle.
Starting with front-end since it's a bit easier to jump into
Back-End C#, front-end SPA in F#
Check out Fable-Elmish (and Fable-Elmish with React (Elm-style model-update-view for React)) https://github.com/fable-elmish/elmish
WPF Desktop -> Elmish.WPF (Elm-style model-update-view for WPF) Check-out https://github.com/Prolucid/Elmish.WPF
Back-End Slices for lambda-architecture-style systems
Web,Front-end in whatever, streaming with Storm and F# via FsShelter (and FsCassy for Cassandra, FsBunny for RabbitMQ)
Streaming, front-end in whatever, Web Layer with Freya
Also: Some tips Install VS Code with all the ionide plugins. Also grab Forge to create new fsharp projects if you're not doing net core development. Use Expecto for tests. Then from the editor you can build,run, debug, paket install, and run test(s)
At my company we have a C# codebase for a large web application, but we create a 2 stage caching feature for it in F#. This F# project uses a couple of C# oriented libraries (stackexchange.redis and protobuf-net). So lots of interop going both ways.
Some examples of people using it in production: http://fsharp.org/testimonials/
All of the "real" code in that app is in an F# library, which you add to the Visual Studio solution just like you would any other C# helper library. When you add a source file to that library, it's an F# source file, and it's built with the F# compiler into the library, which is then linked with the C# "main" program.
There are a few tricky parts, owing to the substantial differences between C# and F#. They all come down to the fact that there are aspects of both C# and F# that don't map naturally to the other. While there may be low-level .NET or IL ways to force the call, it's better to restrict your use of each language at the boundary between the two parts of the program.
Some examples:
1. F# has two ways of passing parameters to a function called the tuple and curry forms. Curried functions are the full-power form, but C# can't call them directly, so any function or method you want to export to the C# side must use the tuple form. At a superficial level, the only difference is some parentheses and commas, but at a low level, you're purposely nerfing the F# function to allow C# to call it. This is not an area you can avoid knowing about, since all of .NET uses tupled calling form, being written for C# initially.
2. F# has several native data types that have no direct implementation in C#. Some newer versions of C# have .NET extensions to allow them to manipulate values of these types given to the C# side from the F# side, but given a choice, it's often simpler to restrict the set of data types you define the interface between the two in terms of. That is, you generally don't want to allow discriminated unions, records, tuples, or function values through the boundary, if you can help it. Use data types C# copes with better: classes, structures, lists, and arrays instead.
3. C# code often makes use of null values, which are...well, "sinful" in F#. It is possible to use null in F#, but strongly recommended against, since F# is all about definite value states, and null adds an element of indefinite-ness to the application. You can choose either to allow null values through the C# to F# boundary or enforce the F# side's wish not to accept them at the boundary. Your choice.
4. Once you get into the F# way of doing things, you start to become more choosy about the C# libraries you use from F#, since some are more acceptable from an F# standpoint than others. You start to avoid libraries that have mutable values flying around everywhere, methods with side effects, etc. Some C# libraries are outright annoying to use, because you have to continually cast away so much of the F# value in order to use them. Fortunately, .NET itself is generally pretty good in this regard. The NuGet world shows less restraint here.
And there is the famous line "Functional programming? We did functions 30 years ago. No big deal".
First, the type system is great when it comes to modeling the problem and communicating that model with non-technical project managers because writing good data models often means you write clear code that's idiosyncratic to the language. My experience is non-technical people understand clear data models and pipelines and those are two areas where F# code reads very clearly.
If OOP is your thing, I can argue it's a much better OOP language than C#. From a SOLID and Design Patterns perspective, the language has been streamlined to encourage a good OOP style by default. Design Patterns are simpler (Factory, Builder, Decorator, Adaptor, etc). Dependency Injection is very natural and implementing fluent APIs is a lot simpler.
The biggest benefits come from maintaining good hygiene. You're a lot less likely to have null reference exceptions or introduce invalid states. Race conditions are harder when most things are immutable by default. You're also less likely to encode things poorly because your type system sucks. You'll think more carefully about how you write loops, ifs and switch statements because the compiler catches and prevents you from doing boneheaded things. It's also has features that prevent you from accidentally adding cyclomatic complexity. For example, lower-level modules are not allowed to refer to higher-level modules. It's also harder to accidentally make functions recursive because it requires a special "rec" keyword.
I realize people dismiss hygiene, but this stuff really goes a long way to help manage complexity when it comes to growing and maintaining applications over long periods of time.
I'm not going to claim it's great at everything. It's a wonderful back-end and business language, and it's fantastic at modeling business objects and records. However, the tooling isn't there for doing WPF applications. Also, sometimes you come across issues with libraries that work well with C# defaults but not F# defaults. For example, F# properties tend to be read-only by default, so libraries that hydrate objects with data don't work unless you explicitly make those properties writable.
Nevertheless, if nothing else was an issue (buy in, training, etc), I'd opt to write the business logic in F# 9 times out of 10 times and save C# for the front-end (tooling).
Can you expand on this? I'm interested in how these things are easier in F# than in C#.
"One of our previous posts, Why You Should Use F#, listed a few reasons why F# is worth trying out today"
I would argue F# is a much better business programming language than C#. Admittedly, I am not very good at it, and have barely done more than a few toy programs in it, but F# (like most FP languages) allows you to bake in a lot of the rules into the Types themselves, and immutability combined with a lack of nullness protects you from a lot of footguns.
https://blogs.msdn.microsoft.com/dotnet/2017/05/31/why-you-s...
You can find it here: https://fsharpforfunandprofit.com/ddd/
> Before you begin using Hopac, make sure that you have configured your F# interactive and your application to use server garbage collection. By default, .Net uses single-threaded workstation garbage collection, which makes it impossible for parallel programs to scale.
https://github.com/rspeele/CSharpFSharpPhrasebook
This does not sell the language -- it doesn't show off anything interesting you can do in F# that you can't in C#. There are other resources for "why F#". This is for C# developers who are convinced that they want to learn, but are annoyed by not being able to quickly look up how to do the things that they're familiar with from C#.
http://www.fsharpworkshop.com/ http://products.tamizhvendan.in/fsharp-applied/
Once you are proficient, you will write
- less code for similar functionality
- have lot less dependency cycles
- using Option types over null helps in the long run
- improvement in productivity
The only problem is that you have attain a level of proficiency and flip the "train" of thought from OOP to Functional, and that can take some good time.
1. Immutable values by default avoids whole categories of problems. Just for one example, you can't have a data race between two threads if all the public values accessible from each thread are guaranteed immutable.
2. F# forces all cases to be handled. You've doubtless run into C# code that has a switch statement that doesn't have cases for all possible inputs, and no default case. F# doesn't have a direct equivalent of "switch" at all, but it does enforce completeness in the equivalents it does have. For example, it's illegal in F# to say something like "if foo > 1 then ... elif foo < 1 ..." since that leaves the 0 case unhandled. This is not just about better compiler warnings: it's required by the very fact that "if/else" is an expression, not a statement, so all branches must produce a value for all inputs.
3. F# has units of measure data types. Ever had an application bug because you've incorrectly passed a bare "int" value holding milliseconds to a function expecting seconds? I have. F# lets you define your units as part of the data type, so that it's a compiler error to pass milliseconds to a function expecting seconds.
I could go on, but as you can see, there really are substantial differences in practice between F# and C# code.
cons: performance (doesn't have to be bad but if you do things idiomatically will tend to be) tooling and other externalities (better that most niche languages but not as good as c#)
// Flip the BST using pattern matching!
let rec flip bst =
match bst with
| Empty -> bst
| Node(item, left, right) -> Node(item, flip right, flip left)
Without type annotations, how can it tell the flip takes an instance of BST as the parameter?