hn-classics/_stories/2006/11503087.md

166 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
created_at: '2016-04-15T09:17:33.000Z'
title: Why learning Haskell/Python makes you a worse programmer (2006)
url: http://lukeplant.me.uk/blog/posts/why-learning-haskell-python-makes-you-a-worse-programmer/
author: mrkgnao
points: 59
story_text:
comment_text:
num_comments: 60
story_id:
story_title:
story_url:
parent_id:
created_at_i: 1460711853
_tags:
- story
- author_mrkgnao
- story_11503087
objectID: '11503087'
year: 2006
---
[Source](https://lukeplant.me.uk/blog/posts/why-learning-haskell-python-makes-you-a-worse-programmer/ "Permalink to Why learning Haskell/Python makes you a worse programmer - lukeplant.me.uk")
# Why learning Haskell/Python makes you a worse programmer - lukeplant.me.uk
lukeplant.me.uk
* Site
* [Home][1]
* [About me][2]
* Blog
* [Posts][3]
* [Categories][4]
* Post
* [Comments][5]
* [Related][6]
# Why learning Haskell/Python makes you a worse programmer
by [Luke Plant][1]
Posted in: [Haskell][7], [Python][8], [Rants][9], [Software development][10] — August 30, 2006 at 20:51
Ive found, contrary to what you sometimes read, that learning Python and Haskell has _not_ improved my programming using other languages. Haskell in particular, being so different from imperative languages, is supposed to give new insights into programming that will help you even when you are not using the language. My current experience doesnt exactly tally with this, and here is why:
1. Demotivation.
I find I think in Python, and even in Haskell to some extent, even though I have used Haskell very little. I constantly find myself wanting to use idioms from these languages, or noticing how much less code Id be able to write if I was using one of these languages (which, although very different from each other, are both much more powerful than the language I use at work, C#). Its very common for me to notice that using either of these languages I could decrease a chunk of code by a factor of 2-5, and not rare to see a factor of 10-20 in certain parts of the code base.
Further, my experience with Haskell means that I now see potential bugs everywhere in imperative code. Before, I was fairly well aware of the problems that stateful programming and side-effects can cause, having dealt with many scores of bugs related directly to this, and spent countless hours debugging these problems. But without any alternative, I guess I had just lived with it. Now I know there are other ways of doing these things, I find it difficult to be satisfied with _any_ of the code I write. I am constantly aware that I am writing traps that other people are likely to fall in.
I also find C# code very ugly compared to both Python and Haskell. On the visual level, the mandatory use of braces everywhere (OK, theyre not mandatory everywhere but are enforced by coding standards with good reason) makes code contain a lot of line noise and empty space, and combined with the verbosity of the libraries and type declarations etc, you find that a page of C# hardly does anything. Im also thinking of beauty on the mathematical level, C# is a grubby mud hut compared to the breathtaking, elegant tower that is Haskell.
The net result of these things is to make me very depressed and demoralised. I feel like a human compiler, translating the Haskell or Python in my head into a language which is a whole level lower.
2. Using functional style obfuscates your code when using other languages.
C# has begun to get some features that are more friendly to functional style programming. So, the other day, when faced with a very common situation I tried a functional solution. I have a list of Foo objects, each having a Description() method that returns a string. I need to concatenate all the non-empty descriptions, inserting newlines between them.
The code I wanted to write was this Python code:
"n".join(foo.description() for foo in mylist
if foo.description() != "")
Or this Haskell:
concat $ List.intersperse "n" $ filter (/= "") $ map description mylist
Using generics from C# 2.0 and the methods they contain, the best I got was:
string.Join("n", mylist.ConvertAll<string>(
delegate(Foo foo)
{
return foo.Description();
}).FindAll(
delegate(string x)
{
return x != "";
}).ToArray());
If I had been starting with a different data structure, the C# version would have been even worse — and C# seems to have hundreds of different collection classes, used inconsistently in the .NET libraries. Also I should point out that if you write any methods that accept delegates (the nearest thing to first class functions) you have to declare the function signature for them separately if one doesnt exist already (or if you dont know where to find one that already exists), further adding to the bloat of any functional style code.
There are some big problems with the C# version. The first is that there is very little reduction in size versus the imperative style code, if any. Compare to the tedious loop I would have written otherwise:
string retval = "";
foreach (Foo foo in mylist)
{
string desc = foo.description();
if (desc != "")
{
if (retval != "")
retval += "n";
retval += desc;
}
}
There isnt much in it.
Second, it took me longer to write. I had to do some experimenting to see how much type information I had to add to get it to compile (e.g. adding an explicit cast for the delegate turned out not to be necessary, but I did have to specify `ConvertAll<string>` instead of `ConvertAll`).
Finally, there is the problem that this code will get me into trouble with my colleagues. Why am I writing such complex code — using such advanced features as anonymous delegates — when a simple loop would have sufficed? I actually left my functional version in, but was so embarrassed about it I had to add a brief explanatory note.
The fact is that functional idioms work badly in languages that dont have syntactic support for them. Java, from what I know, would have been much worse. C# suffers in that although some features that enable more functional programming have arrived in C# 2.0 (along with various other language improvements), huge chunks of .NET libraries have not been updated to take advantage of them, and our own code certainly hasnt.
It might be argued that you can still use the _principles_ of functional programming (no side effects, functions depend only on their inputs etc) and get benefits that way, even if you cant use the idioms. In reality, libraries and frameworks designed for imperative languages just dont work like that. ASP.NET is an especially bad example. You develop controls by inheriting from `Control` and then overriding various methods. Most of these methods have no return value and no inputs, and work solely by mutating the state of the object (or other objects). They are then called by the framework in a somewhat subtle and complex order (yes, it is a nightmare to debug).
In fact, applying the principles of functional programming would lead me to use only static methods (no instance methods) as much as possible, avoiding anything that mutates states (or even has the possibility of mutating state). I would use a few ubiquitous, dumb datatypes, and keep algorithms separate from them. This flies in the face of the teachings, or at least the practices, of the main programming paradigm popular today, OOP. I cant apply what I think are good principles for writing code without rejecting the very paradigm of the language and libraries I am surrounded with. Its fairly hopeless.
So, learning Python and Haskell has demoralised me and encouraged me to write code that is bizarre and difficult to understand, and, in the context of an OOP code base, provides little benefit over imperative programming. I have no doubt that in general I am a better _programmer_ for learning these languages, but in my current situation, I am not a better _software developer_ — my productivity has in fact nose-dived. When I get frustrated with the C# code I write, I then go and write it again in Haskell and Python, to demonstrate to myself how much better they are, which is a pointless exercise that only demotivates me further.
The moral of the story: dont bother improving yourself, unless you have the freedom to improve your environment accordingly. Thats rather depressing. Can anyone put a better spin on this and cheer me up?
_Update: I probably should have made it more obvious for some people that the title of the post is not entirely serious, and mainly Im just griping._
## You may also like: §
* [The very minimum you need to know about words][11]
* [Null pointers vs None vs Maybe][12]
* [You can't compare language features, only languages][13]
* [Adventures in Haskell - ODBC under Windows][14]
* [Understanding Monads Via Python List Comprehensions][15]
* [Pyrex and Lisp][16]
* [A Django website that took (a lot) more than 20 minutes.][17]
# Comments §
...loading...
[View the discussion thread.][18][blog comments powered by Disqus][19]
Copyright [Luke Plant][20]
Powered by [Pelican][21]
Atom feeds: [all posts][22] | [comments][23].
[1]: https://lukeplant.me.uk/
[2]: https://lukeplant.me.uk/personal.html
[3]: https://lukeplant.me.uk/blog/
[4]: https://lukeplant.me.uk/blog/categories/
[5]: https://lukeplant.me.uk#comments
[6]: https://lukeplant.me.uk#related
[7]: https://lukeplant.me.uk/blog/categories/haskell/
[8]: https://lukeplant.me.uk/blog/categories/python/
[9]: https://lukeplant.me.uk/blog/categories/rants/
[10]: https://lukeplant.me.uk/blog/categories/software-development/
[11]: https://lukeplant.me.uk/blog/posts/the-very-minimum-you-need-to-know-about-words/
[12]: https://lukeplant.me.uk/blog/posts/null-pointers-vs-none-vs-maybe/
[13]: https://lukeplant.me.uk/blog/posts/you-cant-compare-language-features-only-languages/
[14]: https://lukeplant.me.uk/blog/posts/adventures-in-haskell-odbc-under-windows/
[15]: https://lukeplant.me.uk/blog/posts/understanding-monads-via-python-list-comprehensions/
[16]: https://lukeplant.me.uk/blog/posts/pyrex-and-lisp/
[17]: https://lukeplant.me.uk/blog/posts/a-django-website-that-took-a-lot-more-than-20-minutes/
[18]: http://allunkept.disqus.com/?url=ref
[19]: http://disqus.com
[20]:
[21]: https://blog.getpelican.com/
[22]: https://lukeplant.me.uk/blog/atom/index.xml
[23]: http://allunkept.disqus.com/latest.rss