
F# 4.0 Preview - noblethrasher
http://blogs.msdn.com/b/fsharpteam/archive/2014/11/12/announcing-a-preview-of-f-4-0-and-the-visual-f-tools-in-vs-2015.aspx
======
virtualwhys
This is pretty cool, in my day-to-day language, Scala, we cannot do the
following:

    
    
        [('a',1);('b',2);('c',3)] |> List.map String
    

In F# 4.0 the compiler infers that String takes 2 arguments and extracts the
tuple accordingly.

In Scala we're forced to manually extract the tuple when the recipient
function takes more than a single argument.

    
    
        def plus(a: Int, b: Int) = a + b
        List((1,2),(3,4)) map plus // kaboom
        List((1,2),(3,4)).map{case(a,b)=> plus(a,b)} // ok
    

We'll see where the Microsoft OSS movement goes. If in the not too distant
future we can seamlessly take advantage of, for example, Type Providers and
LINQ-to-SQL/Objects on Linux, I'll certainly give F# a deeper look.

Side note: the next 3 to 4 years will be huge in computing, IMO. Microsoft
stack is coming to Linux and OSX, Oracle is finally pushing forward Java and
the JVM, and FP languages in general seem to be picking up steam in terms of
adoption. Good times ahead for everyone ;-)

~~~
Rizz
And a another way to use tupled is:

    
    
        list map Function.tupled(plus)
    

Hereby additionally proving the old saying 'if you need help with a product
don't say you need help because you'll get hit with RTFM, just say too bad you
can't do X in product while it's easy to do in [competing product], and
everyone will try to prove you wrong.'

~~~
virtualwhys
> and everyone will try to prove you wrong

heh, how true, though more of an invitation; a strength/weakness of Scala is
the fact that there's often more than one way to do the same thing (at least 3
ways have been shown with the current example). From what I've seen F# does
not have this characteristic.

Anyway, ideally the Scala compiler would provide the same level of concision
that for comprehensions do vis-a-vis flatMap/map boilerplate, thus reducing
our example down to: `list map plus`, the bare essentials ;-)

Worth noting that the source for Function[0] indicates `Function.tupled`
methods are slated for removal in future: "these functions are slotted for
deprecation, but it is on hold pending superior type inference for tupling
anonymous functions"

[https://github.com/scala/scala/blob/v2.11.4/src/library/scal...](https://github.com/scala/scala/blob/v2.11.4/src/library/scala/Function.scala#L72)

------
louthy
It's great to see the gradual improvements in F#. I think it's a brilliant
language. I was initially not too sure, because, even though I've been coding
C# for a long time, my first foray into the functional world was Haskell -
which is a stunning language. But when it comes to plain old let's-get-things-
done pragmatism, F# wins out imo.

------
galago
It would be useful if someone knowledgeable _and_ critical could explain
clearly the use of this language. The marketing blather doesn't give me much.
I'm not a software engineer, so this just seems like a bunch of syntax
wankery. I'm probably wrong, I'm just looking for a brief explanation as to
why.

~~~
noblethrasher
Really short answer:

F# is to C# as C is to Assembler (I regularly use both C# and F# and don't
quite agree with this, but it is defensible).

Short answer:

Programming, especially OOP, has a lot of prescriptions: things like coding
against interfaces rather than implementations, using abstractions, the law of
Demeter, avoiding mutations, prefer composition to inheritance, etc.

Basically, you can think of F# as a language that compiles down to C#, but
follows all of the best practices without fuss.

Consider this example of F# code:

    
    
    		type Shape =
    			| Circle of float
    			| Square of float
    
    		let area s =
    			match s with
    			| Circle r -> Math.PI * r * r
    			| Square sd -> sd * sd
    			
    		let perimeter s =
    			match s with
    			| Circle r -> 2 * Math.PI * r
    			| Square sd -> sd * 4
    
    

Here is the moral equivalent in C#:

    
    
    	 public abstract class Shape
    	 {
    	 	public abstract float Area();
    	 	public abstract float Perimeter();
    	 }
         
    	 public sealed class Circle
    	 {
    	 	readonly float r;
    	 	
    	 	public Circle(float r)
    	 	{
    	 		this.r = r;
    	 	}
    	 	
    	 	public override float Perimeter()
    	 	{
    	 		return Math.PI * 2 * r;
    	 	}
    	 	
    	 	public override float Area()
    	 	{
    	 		return Math.PI * r * r;
    	 	}
    	 }
         
    	 public sealed class Square
    	 {
    	 	readonly float side;
    	 	
    	 	public Circle(float side)
    	 	{
    	 		this.side = side;
    	 	}
    	 	
    	 	public override float Perimeter()
    	 	{
    	 		return 4 * side;
    	 	}
    	 	
    	 	public override float Area()
    	 	{
    	 		return side * side;
    	 	}
    	 }
    

A couple of things to note:

* The C# code needs 5 times as many line as the F# code (adding a new shape to F# will require about 3 lines, but the corresponding C# class definition will be at least 15 lines).

* The F# code is idiomatic, but hardly any C# programmer seals classes or defines them as immutable by default, even though it is a good practice.

That said, there are some advantages that C# enjoys. Consider our example
code: Even though C# requires more lines of code to define a derivative of
Shape, at a certain point it will _always_ be easier to add new classes to C#
than the corresponding variant to F# (see "The Expression Problem" \- on the
other hand, adding new functions that apply to Shape will be easier in F# than
adding the corresponding new methods in C#). Also, F# is supposed to be a
hardcore statically-typed language, but there are some advanced concepts (e.g.
type classes) that are easy to realize in C# yet not in F#.

~~~
CmonDev
I noticed you sealed the C# classes. What if you want to keep it extensible,
which makes sense? How will that extensible pattern matching look then?

Also would be interesting to see how long would C#6 code be (twice as short?).

Apart from the sample, I also don't understand why F#'s naming patterns are
not consistent with the rest of .NET (in terms of starting letter case). Feels
alien.

Also how come this was considered a sane syntax for arrays?

[|1; 2; 3|]

instead of

[1, 2, 3]

Even Haskell's syntax is less alien.

~~~
noblethrasher
Not to mention indexers.

Well, programming languages do have a prescriptive aspect. Arrays in C# 1.0
were more fundamental than List whereas the situation in F# 1.0 was the
reverse, and F# doesn't really want you to use arrays as much as it wants you
to use list.

...

Personally, I always mark my classes as either sealed or abstract. In OO
terms, I only care about extending the Shape class, not the individual
subclasses because those themselves are are already extensions... of the Shape
class. If I did want to extend, say, the Circle class, I would probably make a
new abstract class called Ellipse that derived from Shape and then derive
Circle from Ellipse.

But, I don't really think in strict OO terms any more. C# has a decent type
system (despite what my fellow ML programmers might say), but one of the
mistakes of the language (i.e. the spec) is that it conflates types with
classes. Those are different things. You may see three classes, but I see one
_type_. In this case it's a sum type called Shape that ranges over Circle and
Square. A sum type , as you may know, is just the type-theoretic version of
logical OR.

Indeed, it wasn't until I learned about sum types that I finally understood
why you would use an abstract class as opposed to an interface: abstract
classes are for when you want to say that a Foo is a Bar _OR_ a Baz _OR_ a Biz
whereas interfaces are for when you want to say that Foo is a Bar _AND_ a Baz,
_AND_ a Biz.

~~~
CmonDev
> _" In this case it's a sum type called Shape that ranges over Circle and
> Square"_

How do I extend Shape to include Triangle without modifying the current code
(e.g. in a separate file)?

~~~
noblethrasher
You would have to modify the code, and as I mentioned, it can be pretty
painful in F# and other ML languages if you already have a bunch of functions
that apply to Shape.

Subclassing is a good and useful tool that simply works better in C# than F#.
But, just as importantly, class hierarchies are often a poor way to model a
problem.

~~~
CmonDev
Fair enough, thanks for answers.

~~~
noblethrasher
You're welcome.

It just occurred to me that you may have been asking about extending Shape in
the C# example. In that case, you'd just subclass Shape as normal[1]. Some
people argue that sum types shouldn't be extended, but I never really
understood that. Basically, C# lets you define unbounded sum types (in the
form of subclassing) whereas idiomatic F# more or less demands that you know
up front how many variants you're going to need.

[1] Although, sometimes I do define my classes to prevent this by marking the
constructor(s) of the abstract base class as private, and then writing the
derived class definitions within the body of the base class.

~~~
CmonDev
I have seen opinions that C# is good for architecture and F# is good for
implementation of components. I might opt for such an approach. Really wish I
had a default non-null immutability in C# though.

------
gnuvince
Very cool. After my M.Sc. I'm going to need to find a job, and since OCaml
jobs are pretty much inexistant in Montreal, F# is my backup plan.

~~~
genwin
Good thinking to be considering the demand. Why not a remote job? Also
consider the trend. There's a site that ranks language popularity on a
periodic basis.

------
DanielBMarkham
Normalized collection modules is a big plus. It was always a pain having to
cast something out of one thing and into another just to get some method that
should have been there in the first place. Same goes for slicing.

Some good stuff, guys!

------
jbeja
I can't wait for .NET to be ported to Linux to try this, it looks awesome.

~~~
steego
Stay tuned: There are already a number of docker containers with F# on them
using Mono. Because the F# compiler is open source, you can probably create
your own container pretty easily based on the preview builds.
[https://github.com/crosbymichael/fsharp-
docker](https://github.com/crosbymichael/fsharp-docker)

------
fallat
If I've already been learning Haskell, should I keep going or stop, drop
everything and learn F#? I'd like someone with F# and Haskell experience to
answer.

~~~
louthy
Depends on your requirements. I use F# day-to-day, but I think Haskell overall
is a better language. There's some ugly aspects to F#, like its OO grammar,
lack of typeclasses and seeming randomness to the casing (sometimes camelCase
and sometimes PascalCase). These are all artefacts of it being a pragmatic
tool in a toolset: its requirement to work with other .NET languages and
frameworks (and Mono).

So for a bit of ugliness, and some loosening of the type-system shackles, you
get a whole ton of stuff.

Haskell as I'm sure you're aware is much stricter and much harder to
interoperate with. But much more refined as a language. Whilst you do get the
"If it compiles it will probably work" thing with F#, it's nowhere near the
level of Haskell. Haskell tends not to play as well with Windows, but again it
depends what you're doing. I've had very few problems with Haskell on Windows
by writing stand-alone services that talk to the rest of the world through
RabbitMQ.

So if you're writing something that must absolutely be provably sound, doesn't
need to talk to much else, then I'd go with Haskell. If you need lots of core
Windows features it'd probably be best with F#.

I went from Haskell to F#, and I'm glad I learned Haskell first because it
gave me a much stronger grounding in functional concepts. It's much easier to
'break the rules' in F#.

I hope that helps.

~~~
fallat
Yes, thank you for your explanation, it was great.

That is why I've started with Haskell too (6 months in now), because it
teaches you the fundamentals about FP, and is strict about it (a good thing in
my opinion).

That being said, I will continue to use Haskell. I know C# and I'm sure the
jump won't be too difficult if I ever need it.

~~~
louthy
Yep, the jump from Haskell to F# is quite easy. It's a shame that F# doesn't
put Computation Expressions up front like Haskell does with monads. The times
when I feel like I'm getting into a mess with F# are nearly always fixed with
monads (passing state around for example).

The nice thing with F# is that [if you have C# experience] you can pretty much
just fall back to the standard .NET framework library if you get stuck. And
the fact that F# supports dot notation means intellisense works. I've found
over time I use the core BCL less and less as I retreat to a more pure
functional approach however. Again, a good grounding in Haskell will help you
there.

------
FlyingSnake
F# is a wonderful language, albeit I'm still getting used to style.

Is anyone here using F# for real project? It would be great to see it in wild.

~~~
DanielBMarkham
Bunch of folks are. I've used it for several. I think there have been a couple
of AskHNs for this.

I'd show mine but you wouldn't see any code! My latest is
[http://newspaper23.com](http://newspaper23.com)

I use F# to generate static pages. This allows me to completely decouple the
back-end from the display. I don't have interactivity yet, but I really don't
see a need to add a framework to get it. F# and mono allows me to shoot for
brutal simplicity. I like that. Many times projects that might be huge
monstrocities in other languages turn out to be just a few well-coded modules
running as Unix-y microservices in F#.

People are starting to give F# a lot of love as a .NET language, then
wondering "Where's the framework?" I'm coming around to the conclusion that it
works best when there is no framework. Fun times ahead.

~~~
noblethrasher
> People are starting to give F# a lot of love as a .NET language, then
> wondering "Where's the framework?" I'm coming around to the conclusion that
> it works best when there is no framework.

Yes, in F# and other ML-like languages you tend to use libraries more than
frameworks.

(I'm the original poster, and I've been extolling the virtues of ML-style
functional programming throughout this thread, but I still owe you an email
explaining why I think OOP is ultimately better than FP)

