

Learning Haskell/Python makes you a worse C# programmer - jipumarino
http://lukeplant.me.uk/blog/posts/why-learning-haskell-python-makes-you-a-worse-programmer/

======
gecko
I think the author is simply inexperienced in C#. Here's the right way to
express his code:

    
    
        string.Join("\n",
            from elem in myList
            where elem.Description != ""
            select elem.Description);
    

Note how mind-numbingly close this is to the Python:

    
    
       "\n".join(foo.description() for foo in mylist
                             if foo.description() != "")
    

I also think it's considerably easier to read than the foreach loop.

~~~
resurge
Note that this article is from _2006_. Hence his using of C# 2.0 instead of a
later version which includes Linq.

~~~
kenko
Linq, which was inspired by ... Haskell!

Would it be irresponsible to speculate that this article is directly
responsible for the inclusion of Linq in C#? It would be irresponsible not to
speculate!

~~~
pjmlp
LINQ was introduced by Erik Meijer, an Haskell researcher working on .NET
team.

[http://research.microsoft.com/en-
us/um/people/emeijer/papers...](http://research.microsoft.com/en-
us/um/people/emeijer/papers/es012-meijer.pdf)

~~~
rjzzleep
a true gem, thanks for this. where did you find out about this paper?

~~~
pjmlp
I read a lot research papers, specially related to compiler design.

------
omgtehlion
TLDR: C# 2.0 had ugly syntax. article from 2006

in c#3.0 we write

    
    
      string.Join("\n", mylist.Select(x=>x.Description()).Where(x=>x != "").ToArray());
    

and now

    
    
      string.Join("\n", mylist.Select(x=>x.Description()).Where(x=>x != ""));

~~~
njbooher
A method named 'where' seems really odd.

~~~
mwg66
Why? It's a fluent interface.

~~~
njbooher
It's not a verb.

~~~
kooshball
Using Select and Where makes perfect sense.

~~~
markokocic
In SQL it does.

~~~
kooshball
The whole point of LINQ is to add query-like functionalities to C#. LINQ
stands for "Language-Integrated Query"

from <http://msdn.microsoft.com/en-us/library/bb397926.aspx>

"Language-Integrated Query (LINQ) is a set of features introduced in Visual
Studio 2008 that extends powerful query capabilities to the language syntax of
C# and Visual Basic. LINQ introduces standard, easily-learned patterns for
querying and updating data, and the technology can be extended to support
potentially any kind of data store. Visual Studio includes LINQ provider
assemblies that enable the use of LINQ with .NET Framework collections, SQL
Server databases, ADO.NET Datasets, and XML documents."

------
binarymax
It is unfortunate, that the type of positions that employ .NET developers,
enforce C# (or sometimes VB.NET) as their language that targets the CLI. While
I understand the need for consistency, it would be nice if IronPython or F#
were accepted. But dont just feel defeated, make a case to your architect or
manager, they might be open to it. However its worth noting that in my
experience, C# is a fine language - especially if you can move past .NET 2.0
and use lambdas and LINQ.

~~~
gecko
I think part of the problem is that, while the CLR is _vastly_ better than the
JVM at supporting languages other than its flagship, I also think that the
cost of using languages other than C# or VB.NET is higher than a lot of
developers are willing to admit.

We just allowed some F# code into Kiln. On the one hand, it was vastly simpler
than the C# code it replaced. On the other hand, we had to rearchitect our
solution layout to handle changing the build order, which we in turn had to do
so that the F# code could be sanely usable from the C# code and vice-versa,
which in turn required writing a lot of call-site boilerplate and type
converters (from C# to F# types). Add in that the CLR is simply not as
optimized for F# as for C# (or vice-versa, depending on how you want to view
things), and it's not exactly a situation where you can simply say, "Well, F#
is better than C# at expressing this problem, so let's use it here."

I want to be really clear on this: I don't think these problems are any worse
on the CLR than they'd be on the JVM or with native tools (e.g., OCaml calling
C or vice-versa). In fact, they're better in many ways: you have the BCL for
your primitives, rather than the native C ABI (for native), and you have a VM
that is legitimately much less tied to an individual language than the JVM,
which makes things like tail-recursive languages a lot simpler. But I think
the right way to regard Foo# languages is more-or-less the same as any other
language: unless you can write the entire project in Foo#, think hard about
whether the cost of interfacing between Foo# and C# is worth it to your
project. Most of the time, it isn't.

~~~
danek
Also consider that it is hard to hire people to work on your project if you
use F#, whereas c# has enough similarities to other languages that it is easy
for people to get up to speed. It's too bad, F# is a really great language.

~~~
markokocic
> Also consider that it is hard to hire people to work on your project if you
> use F#, whereas c# has enough similarities to other languages that it is
> easy for people to get up to speed.

Also consider that HR departments and some engineers falsely assume that it is
hard to hire people to work on your project if you use F#, whereas c# has
enough similarities to other languages that it is easy for people to get up to
speed.

~~~
danek
lolwut?

Do you disagree that C# has similarities to other languages? C# is based on
Java, which is somewhat based on C++. Basically anyone who does a CS course
learns one of these. In comparison, I don't know any programs that use
Haskell, oCaml, scala, or ML (I had a single class in which I had to use ML
fora single project). What I mean to say is, functional programming is not
widely taught. I don't think this is controversial.

Do you disagree that any person that is reasonably smart and that you'd want
to hire could become productive in c# within a few days, given that they've
used java or C++ before. This is a super-low risk gamble. I don't think this
is controversial.

The only indicator that someone can become productive in F# is that they have
experience in one of F#, Lisp, ML, Haskell, etc. I don't think this is
controversial.

Hiring people is hard. Maybe you haven't been involved in the process, but you
have to interview hundreds of people just to find that one person who is
smart, is a culture fit in your company, and has enough self-discipline and a
high-enough level of consciousness to go about their work in a pragmatic and
intelligent manner.

Now imagine that you are CTO of a new company and you are deciding between c#
and f#. If you startup becomes successful, you'll have to quickly ramp up in
hiring engineers. If your startup doesn't become successful, you'll quickly
have to ramp up in having someone else hire you.

Assuming we are a rational person, that is we are doing a startup in the hopes
that it will be successful, then our plans will facilitate the hiring of many
engineers.

Fast forward to when we need to hire many engineers. Also, remember you don't
have loads of time to spend doing this, because you're the CTO of a startup
and you have shit to do. Also, remember it's hard for startups to hire because
1) risk and 2) you aren't google.

Now imagine taking your pool of candidates and reducing it by 99%.

------
stcredzero
_> The fact is that functional idioms work badly in languages that don't have
syntactic support for them._

You can even remove functional from the sentence. Powerful features of
languages like Python and Lisp don't get you more power than languages like
Java. They give you more power per unit of effort.

~~~
wging
The definition of power is energy per unit of time. Similarly, the common
usage of the word _power_ as applied to programming languages means pretty
much that: you get more out of your work. In this analogy _energy_ would
correspond roughly to _computability_ , which is not quite so useful a concept
to measure. (Of course the analogy breaks down--energy can be indirectly
measured, but computability is a yes-or-no question.)
<http://www.paulgraham.com/power.html>

------
pcote
I'm a Python guy with a Java day job so I'm guessing my situation isn't that
different from what he dealt with in 2006. Heck, most of us Java guys are
dealing with it in 2012!

Python didn't drag my day job down. Instead, it gives me the understanding of
what Java's shortcomings are and why IDEs and frameworks exist to cope with
them.

It also changed the way I looked at design patterns. Before I knew Python,
they were pretty intimidating. Now, I look at a strategy pattern
implementation and find it more a cute attempt to compensate for something
than anything else.

------
rjzzleep
well i completely disagree. he's got a point in his first paragraph, maybe a
little different though. If all you saw is C# code from C# people you won't
care one bit about the disgusting mess they create.

But if you've learned a whole range of languages you'll try to come up with
more elegant solution. He tried that, but as gecko pointed out the errors were
not in trying, but rather in his results.

I work in a C# dev house now, and boy what is considered a good solution there
(and in their contractors works) is so sad I don't even know what to call it.

But then, you look at the latest c# version and it has quite a few interesting
features, people just don't use it. My guess is that they've just been doing
it since c# 2.0. And the fact that c# is not really made for web development,
which is what it seems to be most taught doesn't really help either.

------
hippich
Or in perl:

    
    
      join "\n", map { $_->{description} } grep { $_->{description} ne "" } @mylist;
    

sorry, every time i see something like this, i just can't resist to post code
in Perl. =)

~~~
cygx
I'll see your Perl5 and raise you some Perl6:

    
    
        @list.map(*.description).grep(?*).join("\n")

~~~
gecko
That is starting to look more like J or K than Perl. Is the Perl 6 team still
considering syntax changes? If so, any thought on making map/grep/join
operators?

~~~
cygx
map, grep and join are subs as well as methods. Perl6 is a multi-paradigm
language and of course _there's more than one way to do it_ \- even when using
the same operations.

Instead of chaining methods, one could also use

    
    
        # p5 style
        join "\n", grep ?*, map *.description, @list;
    
        # dataflow style
        @list ==> map *.description ==> grep ?* ==> join "\n";
        join "\n" <== grep ?* <== map *.description <== @list;

------
tkellogg
Wow, this is the worst article I've seen on hacker news front page in a very
long time.

C# has a tremendous potential for functional programming. There's some
features that make a pure functional style easier and prettier in haskell, but
C# has plenty of potential.

The title is total link bait. I clicked because I know there are things to
write about - like pervasive nulls and mutable-by-default variables to begin
with. There really are things to complain about! But the actual contents of
the article are infuriatingly obtuse.

The fact that 39 people found this interesting in 2012 just demonstrates how
ineffective the entire hacker news concept really is.

~~~
olmobrutall
I totally agree with you. Sometimes the anti-MS feeling here is absourd.

C# is an amazingly designed multiparadigm language with excellent tooling that
works in plenty of OS and devices. If it will come by google the open source
world will be wet already. Having an ideology is ok but shouldnt be confused
with technical merits. Some examples:

IQueryabe<T> and expression tress let you write expressive queries that run on
the database but have compile-type checking. Amazing for mantaining big
datacentric apps.

Async/await let you write complex asynchronous code as if it where usual
imperative one. With for, try catch, etc... The compiler changes it for you.

And all this on a real language that runs fast and you can use in your work to
build phone apps, web apps, win apps and also, but not just, compilers and
authomatic theorem proving applications.

------
PaulHoule
C# has gotten much better since that article was written, but I've still got a
'bag of tricks' that I feel guilty about such as properties that return
delegates and such.

I like using functional methods in Java to implement DSLs but the guava docs
are right when they say you shouldn't be ashamed to use a for loop from time
to time in Java.

------
tinco
People should not be so eager to jump to the new functional constructs in C#
to proof it can be cool too. There is no shame in imperative programming, it
has its own advantages and can be pretty too.

In this case, just using C# a bit more idiomatically can go a long way:

    
    
      var descriptions = new ArrayList(mylist.Length);
      foreach (var foo in myList)
      {
        if (foo.Description == "") { continue; }
        descriptions.Add(foo.Description);
      }
      return String.Join("\n", descriptions); 
    

The names the author gives to his variables are the first indicator that he
just isn't really in a C# mindset.

~~~
noblethrasher
The spirit of your code is correct but I think you'll get a runtime error
since the inferred type of your iteration variable, foo, will be
System.Object.

Here's a slightly more idiomatic C# 2.0 (i.e. sans _var_ goodness)

    
    
      ArrayList descriptions = new ArrayList(mylist.Length);
      
       foreach (Foo foo in myList)
        if (foo.Description != "")
            descriptions.Add(foo.Description);
      
      return String.Join("\n", descriptions);

~~~
tinco
Hey, you're right, it would be a compile time error but indeed. I'd rather
supply a generic constraint <Foo> to ArrayList than have it be cast to Foo
that way (does it even do that automatically?).

Also, do you think leaving out the braces is idiomatic? I think it looks
really pretty but I don't like it at all, it is too brittle.

~~~
noblethrasher
Eliding the braces does make it a bit less idiomatic I suppose; but in ten
years of programming I don't think I've ever been bitten by a bug caused by
that style... not even in JavaScript.

On the other hand, I think the risk of making the code _slightly_ more brittle
is worth it if it makes it much more pleasant to read. Whenever I see a
for/foreach followed by a single statement then I know that the code is doing
a simple projection (i.e. Select in Linq or SQL parlance). If it’s a
for/foreach followed by an if statement followed by some other statement (as
in the above code) then I know it’s a simple filter and projection (i.e. Where
and Select).

But I wanted to illustrate your larger point, which is that C# programmers
shouldn’t be so quick to use functional idioms since imperative code can not
only look just a pretty, but it’s almost always slightly more performant since
it doesn’t imply as many allocations and indirections.

------
klibertp
Anybody knows if the author moved to programming in Python or Haskell since
then? He should...

