News for hackers. Stuff that matters.
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.