Hacker News new | past | comments | ask | show | jobs | submit login

I'm mostly a C# programmer by trade, and having tried F# multiple times (last time by doing half of the AoC in F#) , I haven't felt that I'd be ready to make the jump. My main issues were:

- Much of the functional stuff like map/filter is available in C# as Linq, which granted, is not as nice, but the difference is not huge.

- Much of the new stuff in C# like ValueTuples does make it into F# but with a godawful syntax, I don't think this is the language's fault, but rather is the result of Microsoft's inattention

- I'm still not sold on the idea of functional languages - much of the stuff in them, like map/filter, option chaining, high quality type inference, pattern matching has shown up in procedural languages (they are all available in C# with the exception of option chaining), and the downsides, like immutability making some algorithms impossible to implement, is great. Imo, local mutation is not that bad, and functional languages actively prevent it, while global mutation is still a thing, which tends to be more problematic

- The generated .NET IL is not great. seq turns into an IEnumerable, list is some sort of linked list, I'm pretty sure you'd get pretty terrible performance if you did this.




> high quality type inference

C# type inference is not really comparable in any way to F#'s ML-style global type inference. You can realistically write a non-trivial F# program without a single type annotation. C#'s type inference is local: the type of a variable solely depends on the type of the expression on the right. F# uses global type inference, where all expressions of a program are used to infer the types of variables. This means that you can e.g create a list with just [], and then latter append a string to it, which the compiler uses to infer the type of the list.

Both approaches have their upsides and downsides (a program without a single type annotation is really hard to read without the help of an IDE), but they are clearly very different.


>high quality type inference, [...] available in C#

This is not what I would say at all, the only thing that C# offers in type inference is the ability to use "var" when initializing a variable to save yourself the tedium of writing an obvious type, I have heard something about generics too but I can't remember what it does exactly.

This doesn't hold a candle to F#'s ML-like inference : omitted function argument types and return type, automatic generalization, the ability of the compiler to tolerate individual expressions not being obviously typed right away as long as function-level-context eventually makes it clear what all things are. C#'s type inference is pitiful and trivial by comparison.


If I remember correctly, in F#, all methods are generic unless you say otherwise, while in C#, you have to make it as such specifically. Also there's things, like you can't do generic operator overloading, but in practice C#'s type inference is good enough that you don't need to manually insert the types most of the time.

You can write stuff like var totalLength = Strings.Select(x=>x.Length).Sum(); in practice, where everything is generic, yet you don't need to specify the types explicitly.

Having to specify function argument types, and return is a design choice - I think it makes the code more readable than having to figure it out on your own, but I see the appeal of the other approach as well.

To summarize, in some ways F# is better than C#, however for most of these things, the difference is not large enough to matter. I realize that this is not a fair comparison as far more work and attention was spent on C#, but still it is what it is.


> Imo, local mutation is not that bad, and functional languages actively prevent it, while global mutation is still a thing, which tends to be more problematic

F# also allows and encourages local mutation. In fact, it even allows global mutation without any issues.


Different data structures have different tradeoffs that are used for different contexts. Usually arrays are faster than a linked list however I've seen arrays been used pretty badly as well with GC pressure and LOH pauses hence all the ArrayPool, MemoryPool, stuff added recently which mitigates it a little except when you need to hold it for a little longer than the current method/call. When a simple linked list would of GC'ed much easier than a contiguous block of memory (i.e. GC speed/stability more important than the slight gain in iteration speed, and a lot safer especially in high allocation paths). F# offers extra collections based on some patterns you may want to do there (e.g. recursive loops are easier with linked lists than arrays for example) but doesn't set out to provide its own mutable collections given .NET provides those already.

Type inference isn't really in C# other than some simple parts, nor are some of the features that sometimes give F# an advantage with performance that I've used. When you get used to it I find I have to transpile some problems to C# how I would write them in F# with duplication to get the same performance depending on the problem.

If you are used to C# that's fine. Using both I still think F# is usually the better language these days if your coming into it from scratch, although if you aren't maybe the "sunk cost" isn't worth it?


> The generated .NET IL is not great. seq turns into an IEnumerable, list is some sort of linked list, I'm pretty sure you'd get pretty terrible performance if you did this.

Functional languages have completely different data structures. What is intuitively fast in C# (arrays) may be terribly slow in FP. For example, Erlang (and hence Elixir) are far slower than C# in single-threaded tasks. But, immutability of data allow for incredible parallelism. F# allows mutability, but the default is immutable data.

I remember quite some time ago, when ASP.NET could handle a few thousand connections, Elixir team achieved 2 million concurrent connections with just a few tweaks to the Elixir codebase.

[1] https://phoenixframework.org/blog/the-road-to-2-million-webs...


> the downsides, like immutability making some algorithms impossible to implement

F# like Ocaml has mutability. You can use references for local mutability and if it makes your code easier to write or more clear no one will bat an eye. Immutability seems to me as mostly an Haskell obsession. ML languages have always been very pragmatic on this matter.


> I haven't felt that I'd be ready to make the jump. My main issues were: - Much of the functional stuff like map/filter is available in C# as Linq, which granted, is not as nice, but the difference is not huge.

That sounds a lot like "I don't see a need for functional languages because I'm already using them as libraries" ;-P

> Imo, local mutation is not that bad, and functional languages actively prevent it, while global mutation is still a thing, which tends to be more problematic

Many functional languages allow for local mutation as "cell" objects, if you want to abandon the purely functional paradigm for some encapsulated parts.

And you can do global mutation in a functional way, you just need to handle it with functional state-change idioms that maintain the referential transparency of the code (e.g. the State monad).




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: