All I want is easy syntax for immutable records, and C#-like a fluent syntax for .WithPhoneNumber(phoneNumber) etc. Seems like it'd be a cinch to implement, and for me the single handiest feature from F#.
In F# these are "guaranteed" to be non-null, even though null instances come up during deserialization all the time. In C# use cases, I don't think the non-null "guarantee" should be made or implied, just a POCO.
You have to override Equals() and GetHashCode() for starters. Then you also need to make sure you only have getters and no setters (or private setters). In some cases you need to make your empty constructor private and force a specific constructor to be used. If you have multiple constructors it means you will have different invariants which puts you in class land, you are better off with classes then anyway. Also if your immutable objects have many methods..that also puts you in class land.
Just that alone makes it cumbersome.
So a new record type that behaves somewhat like a struct would be perfect. Or the F# way, which is basically perfection.
I would love to see pattern matching and at least some kind of tuple support. I don't know if it's ever going to happen in C# though...
The `using` static is actually really good news. I have seen people who seem to be really mad about it, but sometimes it would be nice to have, for example:
// Something like Scala's 'Predef'
public static class Id<T>
{
public static Func<T, T> Identity { get { return x => x; } }
}
and then do:
using Id;
var grouped = list.GroupBy(Identity);
Considering you can already open modules in F# (which are compiled down to static classes), it seems that feature found its way to C#. So maybe there is still hope for pattern matching and tuple support :)
Equivalent of F#'s record types would be also awesome, which is what you put as 'readonly class':
type Person = { FirstName : string; LastName : string }
let single = { FirstName = "Jane"; LastName = "Doe" }
let married = { single with LastName = "Smith" }
It seems that this structure could be implemented in C# with inheritance (to add new entities) and extension methods (to add new operations) and var keyword to achieve type inference to verify correctness at compile time.
How do you do functional programming in C#? It has lambda functions, but it lacks sum types, pattern matching and immutable collections (they exist, but it's not much use if none of the libraries use them).
1) Immutable collections is a bit of a pain in C# right now. No LINQ To() methods, some nugets don't actually work with them, constructor methods can be nicer...
His item 4 is to some extent a result of the limited immutable support (he mentions "a lightweight way of building immutable list/collection expression"). Fix that support and 1,4 out of his list are not much of a problem anymore or at least ameliorated.
2) I would be glad to never need hear of IComparer or IEqualityComparer again, which I only need due to the stdlib leftovers... Admittedly not much, but enough to be annoying. His solution is more general, but your idea is very nice. Why didn't I think of that?
5) Dynamic is there for the Dynamic Language Runtime and for dynamic code far more general than your example. It should be kept in that silo, but it does do its job there.
IMHO, the author tries to write C# with the current trend of functional+immutable, and that's why he ended up hitting these issues. It's true that the OOP way isn't bad (at least with those examples), but it's also true C# could offer better support for doing things the other way without much effort.
Regarding immutability, C# 6 makes it a lot easier to write immutable types even for quick prototyping with get only properties:
public string Example { get; }
You can set it in the constructor and only the constructor.
On the other hand in C# it's still relatively hard/annoying to build Structural Equality into your classes (which anonymous types and tuples both handle for you) where the equality of two objects is based on the contents of their properties rather than the equivalence of their references. (Ease of Structural Equality is the number one reason for my typical reliance on Tuple as I tend to use tuples often as Dictionary<K, V>/ILookup<K, V> keys.)
If you are not writing java and you are using lombok then yes, this simple case seems covered well.
I still can’t see how Lombok will help with the exhaustive pattern matching in case the order is a union type of several orders types as explained in my other comment or with avoiding mixing up ms and seconds when using a unit of measure in f# for deliveryTime.
Also I’m curious how you would change just one field of an immutable object with 10s of properties in Lombok and if the resulting java code is as efficient as F# with its immutable data structures that use the copy on write semantics.
I thought about creating a small library that would expose a static IComparer<T> ToComparer<T>(this Func<T, T, int>) extension method (and a similar one for IEqualityComparer<T>). But I so far just was too lazy. If somebody from the C# API team reads this tho.... :P
And while you're at it dear C# team, add .Distinct<TSource, TDest>(Func<TSource, TDest>, IEqualityComparer<TDest>) similar to OrderBy and friends, and various constructors to the generic collection types taking Func<T, T, int> instead of IComparer<T>. Yeah, API bloat, but good one in this case IMHO.
C# and the .NET runtime and the compiler(s) are still evolving indeed, and I would guess a lot of issues will be addressed and fixed in the future.
PS: the most annoying bit to me about the immutable collection library is that they are dead slow whenever I tried them.
This assumes you want to use records for your data: records don't have inheritance. So whereas in C# you could create a UserDb that extends User with the Id/DateAdded fields, in F# that's not idiomatic.
I am sure there could be a good way to automate this using type providers, but I haven't tried it yet.
You can have those semantics in .net, because any hashable can be a dictionary key. It will have a small performance penalty, which won't matter in 99% of cases. You could roll your own collection and get O(1).
F# lets enum values be records, which is the most elegant solution IMO for manageable counts and fields.
It's not as concise as Haskell, but the addition of FP capabilities to C# make it a lot more pleasant as a practical language than it was in earlier days.
var filteredCollection = collection.Where(x => predicate(x));
Immutable records are already possible today in C#, even if a bit more verbose than on F#, plus EF code is anyway mostly generated.
reply