News for hackers. Stuff that matters.
Re:The Problem with F# Evangelism by nickpeterson on Wednesday August 16, 2017 @11:35AM (#15028311)
This article retreads common complaints about the F# experience for outsiders that I've seen numerous time. I'm going to go a different direction.

The problem with the F# community is that they keep asking how to convince C# developers to use F#. I'm convinced that is not the right way to grow the F# ecosystem.

Most C# developers tend to come from enterprise and have a set of values and practices that is generally at odds with open-source, functional languages. They are used to producing codebases that can never be open-sourced, using tooling provided by a single vendor. They don't tend to be the ones contributing interesting or new libraries. In fact, this is a large issue with .NET in general. Most strong libraries are spiritual or literal copies of something from the JVM world.

This urge hurts in other ways. For instance, Don Syme has indicated he doesn't want to put things like Type Classes or Dependent types into the language because it adds a cognitive load to the language that's hard to balance vs the gains in productivity. But their absence means that many of the dev's you actually want contributing to the ecosystem, just use other languages. They adopt Haskell/Idris/Scala/whatever and start contributing blog posts, tweets, libraries, conference talks, etc.

I actually think a large part of this decision is that many of these things would make F# pretty incompatible with C#, which is trumpeted as a feature, but again, it waters down the language to the point that C# dev's look at it and say, "Why bother? It's compatible like VB is, so C# can already accomplish the same things." And in the meantime, it prevents new features that would attract others.

What sounds more enticing to developers, "More Functional C#" or "Haskell With Better Tooling"? What's more, there are even examples of how some of these features could be implemented (both Type Classes and Dependent Typing exist in some capacity through feature requests and F*, an experimental Microsoft language).

Basically, F# should be more about being different than the rest of .net, than trying to be ".net through an OCaml set of glasses".

Re:The Problem with F# Evangelism by rubber_duck on Wednesday August 16, 2017 @11:41AM (#15028368)
I disagree with this, you can sell F# to C# developers - things like type providers for SQL checking their query strings in compile time and no extra build step to produce SQL type definitions vs monstrosities such as Entity Framework... if they've been burned by ORMs to drop to stuff like Dapper they'll love F# type providers.

Immutable data is also becoming a common pattern even in C# but it's tedious as hell to write.

Functional programming is also seeping in but again tons of boiler plate.

Biggest problem with F# is that it has it's own warts + it's a big upfront switching cost and a steep learning curve but it offers many marginal improvements - when you sum those improvements it ends up being worth it IMO but that's a very hard sell.

Re:The Problem with F# Evangelism by louthy on Wednesday August 16, 2017 @12:44PM (#15028950)
> Immutable data is also becoming a common pattern even in C# but it's tedious as hell to write.

I can simplify it for you:

    public class TestClass : Record<TestClass>
    {
        public readonly int X;
        public readonly string Y;
        public readonly Guid Z;

        public TestClass(int x, string y, Guid z)
        {
            X = x;
            Y = y;
            Z = z;
        }
    }
That is an immutable type that has structural equality and ordering, a strong GetHashCode() implementation, as well as a default ToString() which previews the members, and serialization and deserialization constructs. It's a feature I recently added to language-ext [1].

If you need `With` functionality, then add the following member:

    public TestClass With(int? X = null, string Y = null, Guid? Z = null) =>
        new TestClass(X ?? this.X, Y ?? this.Y, Z ?? this.Z);
Then you can use named parameters to do partial updates:

    value = value.With(X: 456, Y: "World");
Obviously it's still more boilerplate than F#, but C# is never going to have significantly less until we get proper record types and ADTs.

> Functional programming is also seeping in but again tons of boiler plate.

Do you have an example? It's something I've worked on quite heavily over the past few years, so I'm always looking for areas to try and improve the lot of C# devs trying to write functionally.

[1] https://github.com/louthy/language-ext/releases/tag/v2.1.0

Re:The Problem with F# Evangelism by rubber_duck on Thursday August 17, 2017 @02:36AM (#15034271)
>If you need `With` functionality, then add the following member:

Without it it's useless - and do that example when fields aren't named X, Y, Z but have actual descriptive property names + 5-10 properties like DB tables.

It gets ridiculous really fast.

>Do you have an example?

Record types, result piping (best you can do is extension methods - again boilerplate), pattern matching, etc.

I recently wrote a C# report integration service - it was a C# service that connected to a DB at specific time intervals, did a bunch of data transformations then passed it off to different services over file system or TCP. Wrote it functional style with C# (immutable collections, record types, static functions).

I then rewrote the same project in F# because I wanted how much simpler the code would be in practice - off the top of my head I managed to reduce a ~20k LOC project filled with boilerplate to ~6k LOC of pure business logic data transformation and protocol specific data formatting. IIRC I had 5 logically grouped source files in F# that had connected logic inside of them (ie. record types were "one liners" defined in the same file they were used not a separate file like the C# tediousness)

The resulting code was easier to read because there was just less crap, easier to test from REPL/debug isolated issues and unit test.

C# is not Java but it's still ridiculously verbose for high level programming.

Re:The Problem with F# Evangelism by jdmichal on Wednesday August 16, 2017 @05:14PM (#15031431)
In C# 6.0 you can also make them properties instead of fields, though I have no idea if this works with your "Record" class.

    public class TestClass
    {
        public int X { get; }
        public string Y { get; }
        public Guid Z { get; }

        public TestClass(int x, string y, Guid z)
        {
            X = x;
            Y = y;
            Z = z;
        }
    }
And C# 7.0 shortens this to:

    public class TestClass(
        int X,
        string Y,
        Guid Z);
Re:The Problem with F# Evangelism by louthy on Wednesday August 16, 2017 @08:46PM (#15032705)
> In C# 6.0 you can also make them properties instead of fields

Why would I want to? It's more boilerplate for no gain. I have never understood the obsession with properties over fields. I realise that to some serialisation or interop libraries that rely on reflection to access properties it's important, but to my mind, those solutions should also support public fields. And obviously inheritance-land with interfaces, but I find writing in a functional style that interfaces tend to be a rarity rather than the default setting.

> though I have no idea if this works with your "Record" class.

Yes, field backed properties are supported in the structural equality and ordering.

> And C# 7.0 shortens this to...

It doesn't. That maybe coming in a later release, but neither C# 7.0 nor 7.1 support the record syntax.

Re:The Problem with F# Evangelism by tjalfi on Wednesday August 16, 2017 @10:49PM (#15033409)
C# 7 does allow one to shorten that class a bit further. I saw this trick in the MEAP[0] of C# in Depth.

    public class TestClass
    {
        public int X { get; }
        public string Y { get; }
        public Guid Z { get; }

        public TestClass(int x, string y, Guid z) => (X, Y, Z) = (x, y, z);
    }
Disclaimer: I don't combine expression-bodied constructors and tuple construction/deconstruction in my code. I will use either feature but the combination seems likely to annoy my coworkers. I also haven't measured the costs of this idiom.

[0] https://www.manning.com/books/c-sharp-in-depth-fourth-editio...

Re:The Problem with F# Evangelism by pjmlp on Thursday August 17, 2017 @02:22AM (#15034210)
> I have never understood the obsession with properties over fields.

Encapsulation, allowing to change the internal representation without requiring clients to update or recompile their code.

Ensuring the class invariants are always kept valid.

Re:The Problem with F# Evangelism by naasking on Thursday August 17, 2017 @04:46AM (#15034881)
> Encapsulation, allowing to change the internal representation without requiring clients to update or recompile their code

This benefit is exaggerated. In practice, classes end up being either record-like where you need visibility on all the actual fields, or they are protocol-like/more fully encapsulated with few public members and more methods. The addition of properties was a big mistake IMO.

Read/write fields should just be part of interface specifications. There is little value beyond that.

Re:The Problem with F# Evangelism by pjmlp on Thursday August 17, 2017 @06:02AM (#15035237)
> The addition of properties was a big mistake IMO.

Properties go all the way back to Smalltalk, which doesn't expose class internal data.

> Read/write fields should just be part of interface specifications. There is little value beyond that.

No because you cannot ensure their invariants, specially if more than one field needs to change at the same time.

Re:The Problem with F# Evangelism by naasking on Thursday August 17, 2017 @06:28AM (#15035363)
> Properties go all the way back to Smalltalk, which doesn't expose class internal data.

Right, because Smalltalk doesn't conflate the use of public and internal members. Properties are second class citizens on .Net, since you can't pass them as ref or out arguments, but we can't use fields which are first class citizens because they have inadequate permissions control.

Then properties exist, but also don't really exist at the reflection level, where you have to search for getters and setters by mangled name if they're private. It's a total frickin mess.

> No because you cannot ensure their invariants, specially if more than one field needs to change at the same time

Properties don't help with changing more than one field either, so I'm not what your point is.

And you can ensure invariants with field permissions, which is what I suggested. Publicly read-only but privately writable is all you need, then the values change via method invocations. Most use of properties just add permissions to field access anyway.

Read/write with default const/init-only fields should have been the default. Then you can't pass read-only fields as ref or out arguments due to permissions, not because they're second class citizens.

Re:The Problem with F# Evangelism by pjmlp on Thursday August 17, 2017 @07:06AM (#15035591)
> Properties are second class citizens on .Net, since you can't pass them as ref or out argument

There is nothing at IL level that prevents it, they can eventually lift the restriction if they feel like it.

> Properties don't help with changing more than one field either, so I'm not what your point is.

The setter can do a cascade set of changes while keeping the invariants.

Re:The Problem with F# Evangelism by naasking on Thursday August 17, 2017 @07:46AM (#15035818)
> There is nothing at IL level that prevents it, they can eventually lift the restriction if they feel like it.

While theoretically true, it will never happen. The whole point of ref/out parameters is efficient, direct pointer access to a member. This can never be made efficient for properties. The CLR GC is carefully tuned to handle internal pointers like this, so quite a bit of engineering has gone into making this efficient and safe, which means efficiency is important.

Furthermore, properties are entirely redundant with the simple change I suggested. They literally serve no purpose once you have permissions on fields, since methods cover the remaining use cases.

> The setter can do a cascade set of changes while keeping the invariants.

And so can methods. If you have mutating this much state, you should be invoking a method anyway. Properties are not the place for sophisticated behaviour.

Re:The Problem with F# Evangelism by MrBuddyCasino on Wednesday August 16, 2017 @02:05PM (#15029680)
You don't increase adoption by making the learning curve steeper.

Rust does its best given the circumstances, but people's top complaint is that its hard to learn.

Scala never went Mainstream because you can't hire developers, and training them takes many months.

F# should not repeat that mistake.

Re:The Problem with F# Evangelism by TensorMetric on Wednesday August 16, 2017 @02:46PM (#15030038)
Adoption of F# would not be a problem if it had .NET Native support and proper tooling

https://news.ycombinator.com/item?id=15026396

Re:The Problem with F# Evangelism by brianberns on Wednesday August 16, 2017 @11:55AM (#15028491)
C# developers in my shop loathe the SQL type provider because it requires them to have a compatible SQL Server database schema at build-time. The extra level of organization required is more than they can accept.
Re:The Problem with F# Evangelism by mbenoni7 on Wednesday August 16, 2017 @02:13PM (#15029765)
There's a new type provider out that takes a different approach by bundling a SQL parser:

https://github.com/rspeele/Rezoom.SQL

It can't check everything that the other providers can, but IMO you get most of the benefit without requiring any onerous build-time dependencies.

Re:The Problem with F# Evangelism by brianberns on Thursday August 17, 2017 @01:12AM (#15033964)
Very cool. Thank you.
Re:The Problem with F# Evangelism by tarmil on Thursday August 17, 2017 @10:52AM (#15037285)
Actually, for the providers from FSharp.Data.TypeProviders, it's only necessary when you need to pull a schema change.

You can pass `LocalSchemaFile = "foo.ssdl", ForceUpdate = false` to the provider, and it will only try to connect to the database if the file foo.ssdl doesn't exist; if it does, then the provider just uses it to compute the schema. When the schema changes, you just need to set ForceUpdate to true, wait for the IDE to pull the changes from the server and write foo.ssdl, then set ForceUpdate back to false, and you can commit the changed file.

Re:The Problem with F# Evangelism by rjbwork on Wednesday August 16, 2017 @12:12PM (#15028645)
Does the F# SQL type provider integrate with the .sqlproj database projects that are in the solution, or do you have to have an actual running SQL database?
Re:The Problem with F# Evangelism by brianberns on Wednesday August 16, 2017 @12:27PM (#15028788)
It needs a connection string to a real database.

http://fsprojects.github.io/FSharp.Data.SqlClient/

Re:The Problem with F# Evangelism by ice109 on Wednesday August 16, 2017 @08:18PM (#15032576)
that kind of thing is a collosal mistake in my opinion - just on the face of it I/o at compile time seems very wrong.
Re:The Problem with F# Evangelism by bonesss on Thursday August 17, 2017 @02:56AM (#15034357)
An understandable position.

Here's the context that makes it not a big deal:

1) If there is some fundamental issue with having a dev DB then you would just use another ORM, just like in C#. Really, this specific type provider is not an ORM, it's for SQL server data munging. Most every project I've seen in a decade has multiple dev DBs, many used in testing, many used for staging... being able to talk to a valid schema source should be relatively straightforward... but if it isnt then get a different type provider or use an ORM with explicit code generation.

2) Compile time guarantees about data sources is a huge source of comfort when dealing with DBs owned by external actors or teams. For data scientist, integrator, sys admins, and such the norm is connecting to operational DBs that you have very little control over. This specific Type Provider ensures that your scripts will not compile if there has been a breaking schema change. That means you're seeing these issues during deployment, not as costly runtime errors that may or may not corrupt your application state. Less debugging, more safety, better guarantees, immediate feedback on issues; all in realtime.

To summarize: if compile time validation of JSON structures, XML structures, SQL Schema, or custom file formats creates some kind of pain, then don't use a provider of types that relies on analyzing data structures to create code :)

For the other 99.9999% of the time type providers are a DREAM for working with external data sources, provide most of what we want ORMs for, and are very lightweight in comparison. It's rapid data exploration with built in prototyping. Very nice.

Re:The Problem with F# Evangelism by brianberns on Thursday August 17, 2017 @01:14AM (#15033972)
Why? Compilers have to read source files anyway. What's wrong with reading other stuff as well? For example, there are type providers for XAML, JSON, app.config, etc. Do they also seem wrong to you?
Re:The Problem with F# Evangelism by com2kid on Wednesday August 16, 2017 @11:59AM (#15028519)
> Functional programming is also seeping in but again tons of boiler plate.

The bar has moved so much on this one. I remember when C#'s wonderful lambda syntax, along with all the extension methods that LINQ added, qualified it as having pretty good functional programming support. Now that other languages have gone out and copied sane lambdas, and "Map" is in libraries left and right, C# has to keep reaching for that higher and higher bar.

Re:The Problem with F# Evangelism by louthy on Wednesday August 16, 2017 @02:47PM (#15030046)
What does the higher bar look like to you? For me, the major missing features of C# are:

* Immutable record types

* ADTs with completeness pattern matching

* Higher-kinds

F# is also missing higher kinds, but can do the others. Did you have something else in mind?

Re:The Problem with F# Evangelism by pjmlp on Thursday August 17, 2017 @02:24AM (#15034214)
None of them makes me write prettier GUIs or better use of EF.
Re:The Problem with F# Evangelism by naasking on Thursday August 17, 2017 @04:51AM (#15034914)
Actually, higher kinds could make you write more composable and reusable GUIs. I don't see why "prettier" is the only metric of interest.

Immutable records also makes it easier to share data safely, thus making scaling across cores easier in some cases, without worrying about plan interference.

Re:The Problem with F# Evangelism by pjmlp on Thursday August 17, 2017 @05:45AM (#15035164)
How do you suggest to make use of higher kinds in Blend?

Immutable records are already possible today in C#, even if a bit more verbose than on F#, plus EF code is anyway mostly generated.

Re:The Problem with F# Evangelism by TensorMetric on Wednesday August 16, 2017 @12:33PM (#15028848)
The real problem with F# is that it isn't supported everywhere C# is https://news.ycombinator.com/item?id=15026396
Re:The Problem with F# Evangelism by dep_b on Wednesday August 16, 2017 @12:00PM (#15028538)
I used type classes on JSON and it's like magic.
Re:The Problem with F# Evangelism by Boothroid on Wednesday August 16, 2017 @12:26PM (#15028785)
I'm interested to know why you describe EF as a monstrosity? Genuine interest, I just started using EF for the first time a few weeks ago for a work project so I've only scratched the surface but it didn't seem terrible, although I did find that only being able to update all tables after a change to the database as opposed to a single table to be a bit of a limitation.
Re:The Problem with F# Evangelism by maxxxxx on Wednesday August 16, 2017 @02:45PM (#15030033)
In all the EF projects I have been on it caused weird issues after a while. Code first projects don't upgrade anymore or the order of saving is wrong or performance is bad.

In pretty much all of them we ended up writing a simple wrapper around the database that was much easier to control.

Re:The Problem with F# Evangelism by Boothroid on Wednesday August 16, 2017 @05:27PM (#15031524)
Useful info.
Re:The Problem with F# Evangelism by cm2187 on Wednesday August 16, 2017 @12:44PM (#15028947)
If you use code first it's very easy to get in a corrupted state where it doesn't know how to update the database. Otherwise it speeds up the basic tasks then it gets in your way to write more sophisticated queries.

I found that a good solution is to write a generic sql serialiser that does all the basic operations (insert, update, select, delete, read one or multiple from readers) and do the rest by hand. It avoids most of the tedious code/sql while not getting in your way to do things like transactions, bulk inserts, etc

Re:The Problem with F# Evangelism by Boothroid on Wednesday August 16, 2017 @01:18PM (#15029270)
Interesting, thank you.
Re:The Problem with F# Evangelism by rubber_duck on Thursday August 17, 2017 @07:28AM (#15035714)
I feel the same way about all ORMs I've seen (minus micro ORMs which I feel are just inferior to F# type providers but work in same spirit) they just try to map two semantically incompatible data models and try to make it look transparent with a bunch of needles complexity - when it ends up failing you're stuck with something that's a hell to debug and tweak.

Contrast that with type providers - they expose SQL to the compiler - this way you get compile time SQL query checking, type checking (it generates types for SQL queries) and it's manipulating data as input and output with known standard SQL semantics.

Re:The Problem with F# Evangelism by jackmott on Wednesday August 16, 2017 @05:32PM (#15031558)
EF is great when things are small and simple. It is when things get big and complex that it can be a hindrance both to understanding what is happening (when does my code actually hit the database?) and how it happens (what query is being generated here?)

Usually the result is performance problems.

Re:The Problem with F# Evangelism by d--b on Wednesday August 16, 2017 @01:11PM (#15029197)
I don't think that's correct. I think the main strength of F# lies in its interoperability with C#.

Basically C# and F# are 2 different languages that are good at solving different problems, and are mastered by different people. C# is a solid infrastructure language. F# is a good business modeling language.

What I think is best about F#/C# is to have data scientists / mathematicians work in a language and have infrastructure people work in another one, and yet have those 2 languages interoperate well.

The main issue for me is that they don't actually interoperate very well...

If F# is pushed too far from C#, what's the point? Just use Haskell...

Re:The Problem with F# Evangelism by yawaramin on Tuesday August 22, 2017 @07:53PM (#15077329)
> If F# is pushed too far from C#, what's the point? Just use Haskell...

But you said it yourself:

> I think the main strength of F# lies in its interoperability with C#.

Re:The Problem with F# Evangelism by platz on Wednesday August 16, 2017 @11:56AM (#15028500)
Type Classes, yes. Dependent types, eh.. that is a bit of a stretch to say the least.
Re:The Problem with F# Evangelism by macca321 on Wednesday August 16, 2017 @12:04PM (#15028586)
I think a better approach is encouraging the use of functional/F# concepts in C#.
Re:The Problem with F# Evangelism by louthy on Wednesday August 16, 2017 @12:29PM (#15028818)
I take this approach in my language-ext project [1]. I wrote it because as well as wanting to use F#, I had a decade old C# project to maintain, and I wanted to bring functional techniques into. We're (my team) finding that the pull to to F# is diminishing quite significantly; this is partly due to the functional framework features I've added to lang-ext; partly the new features of C# (expression bodied members, tuples, etc.), and majorly the relatively poor tooling.

This is not some desire for ReSharper in F#, it's basic stuff like compilation speed, the amount of time it takes for the red-squiglys to turn up (lulling one into a false sense of security), build issues: I have a C#->F#->C# dependency graph in a new satellite project I'm working on. If I change the root C# project then the F# project won't re-build/link, then at runtime I'll get errors that the F# DLL expected a function or type to exist that I'd removed from the C# one. And the absolute classic about the necessity for ordering files in the project in dependency order... I get that this reduces cyclomatic complexity, and that's laudable, but it's just a pain once a project gets to a reasonable size.

For my open-source projects I had to drop F# APIs from the projects because I couldn't create net451 and netstandard1.X project files that would build, pack, and be deployable to nu-get.

Also the interop story between C# and F# really isn't that good. Even though it's shouted from the rooftops as a main selling point. Everything prefixed with FSharp is ugly, FSharpFunc can't implicitly convert to Func, FSharpOption evaluates to null for None, so you get none of the safeness in C#, FSharpAsync is reeeaaally difficult to consume from C#, etc. This means we have to build an interop layer and that always feels like needless effort. It would be much better if there was some tooling support that could create proxies between the F# and C# worlds.

It always feels like there's something in the way. And the way of human inertia is that those seemingly minor niggles will tend to put people off full-scale adoption. I love F# as a language (well, not its OO grammar, but I don't use that), but C# + language-ext actually gives me pretty much everything I need (bar ADTs).

[1] https://github.com/louthy/language-ext

Re:The Problem with F# Evangelism by macca321 on Thursday August 17, 2017 @08:43AM (#15036197)
Re:The Problem with F# Evangelism by throwaway7645 on Wednesday August 16, 2017 @11:38AM (#15028347)
Yes...F# for a non C# dev is a major pain.
Re:The Problem with F# Evangelism by jackmott on Wednesday August 16, 2017 @05:28PM (#15031531)
I am a C# developer who works on a closed source enterprise app at work. I have contributed to the F# core libs and created an open source F# library.
Re:The Problem with F# Evangelism by yawaramin on Tuesday August 22, 2017 @07:54PM (#15077337)
Have you floated the idea of writing some parts of your app in F#? How did that go over?
Re:The Problem with F# Evangelism by DeepRote on Wednesday August 16, 2017 @01:11PM (#15029203)
Incredibly well-spoken.

I've even had devs ask me if we can use Scala instead after a couple days!

Re:The Problem with F# Evangelism by corn_dog on Wednesday August 16, 2017 @03:46PM (#15030612)
Well can they? :) F# is ok but using it makes me really appreciate scala.
Re:The Problem with F# Evangelism by DeepRote on Wednesday August 16, 2017 @04:34PM (#15031138)
I mean they can but we won't get paid if our megacorp overlords don't get their .NET drivel.