Live data from Hacker News

Programming and thinking the functional way

peteratt.com

11–20 of 86 posts

Re: Programming and thinking the functional way

#12

It boils down to the choice between these two alternatives: 1) If it's simple to imagine the computer doing something, it should be easy to program. 2) If it's simple to analyze something mathematically, it should be easy to program. The first path leads to C-style programming with pointers and loops. The second path leads to lazy pure functional programming and beyond. Personally, I'm in the first camp. Small functi…

[deleted]

Re: Programming and thinking the functional way

#13
post #4

Writing quicksort non-functionally doesn't HAVE to be unreadable. Not that I disagree with Haskell being great and all, I just think it's important to realize that imperative != ugly code. public class QS { public List Quicksort (List l, Comparator comp) { if (l.size() lesser = new ArrayList (); List greater = new ArrayList (); T pivot = l.get(0); for (T t: l) { if (comp.compare(pivot, t) out = new ArrayList (); out.…

This will recurse forever when sorting the list [1,0]. Which is why you need to take out the pivot to ensure that the lists you recurse on get smaller and smaller...

Re: Programming and thinking the functional way

#14

It boils down to the choice between these two alternatives: 1) If it's simple to imagine the computer doing something, it should be easy to program. 2) If it's simple to analyze something mathematically, it should be easy to program. The first path leads to C-style programming with pointers and loops. The second path leads to lazy pure functional programming and beyond. Personally, I'm in the first camp. Small functi…

Eh, the list of operators is a weird artifact of the design of lens. The fundamental abstractions at the core are fairly simple, although they're exposed in a scary way.

Most of that has to do with optimizing for reuse and proper type inference. It's a cheat to expose the Haskell subtyping relation for more leverage.

A better way to understand lenses should be to consider a package like lens-family-core which keeps to its roots.

Re: Programming and thinking the functional way

#15

"Wow. i's and j's all the way, what is this? Why is it so long compared to the Haskell example? This looks like comparing C and assembly 30 years ago! And in some respects, it is the same leap." I don't think this is a fair comment considering the in-place Haskell implementation isn't incredibly readable either.

Agreed. I think his overall argument still has merit, but the specific example isn't very good, because Java's quicksort implementation is in-place. He isn't comparing equivalent programs.

Re: Programming and thinking the functional way

#16

It boils down to the choice between these two alternatives: 1) If it's simple to imagine the computer doing something, it should be easy to program. 2) If it's simple to analyze something mathematically, it should be easy to program. The first path leads to C-style programming with pointers and loops. The second path leads to lazy pure functional programming and beyond. Personally, I'm in the first camp. Small functi…

Lens is one guy's pathological abstraction. It's a library, and it's idiosyncratic. It isn't want large Haskell systems "look like".

Cf http://ro-che.info/articles/2014-04-24-lens-unidiomatic.html

Re: Programming and thinking the functional way

#17
post #11

Creating an entire class for the Java version is kind of a disingenuous comparison.

Why? In Java you must place your code within a class, and it's not like in this case it adds a lot of verbosity or overhead. I don't think the author's main argument was classes vs no classes. Java's verbosity is caused by something else...

Re: Programming and thinking the functional way

#18
Ah, the ole "quicksort in 3 lines" argument. There are a few things I take from this.

The good:

1) The definition of the algorithm is clear. It shows "how quicksort works."

2) It's trivial to see (and prove) that the function will terminate, and almost as trivial to prove that it will result in a sorted list. So, it is easy to show correctness.

3) The polymorphism makes this an easily reusable function right out of the box.

The bad:

1) That implementation is very inefficient. At a glance I think it would be O(n^2) time. (Edit: this is misleading, because it's only O(n^2) in the same way that quicksort is always O(n^2). It is inefficient in terms of memory usage, though. And possibly other ways; for instance, I'm not sure how laziness would affect this. But I don't want to be spreading FUD...)

2) The "efficient" implementation given at the bottom is just as inscrutable as any other quicksort implementation I've seen. More so because of the monadic code, single-letter variables (pr?) and opaque library function calls (unsafePartition?) being made. And I'm not even sure that it would work on a list, although since V.Vector appears to be a type class, perhaps list is an instance of it.

3) Both the efficient and inefficient implementations are concise in large part because of their use of library functions. This is often a good thing: Haskell provides a great way to abstract things because of its parametric and ad-hoc polymorphism, and allows for a lot of reusable code. But it comes at a cost too, which is that the actual instructions you're giving to the machine are very far removed from what the computer is doing. Who knows how much code is actually executed, how deep the rabbit hole goes, to translate those beautiful 4 lines into actual machine instructions? With Java, it's precisely visible what the machine is doing to execute your code. This is much less the case with Haskell.

I suppose you could say (broadly) that functional languages excel at expressing what your program should do, while imperative languages excel at expressing how your program should do it. There are cases when you care more about the former, and cases when you care more about the latter. The reason I take issue with the quicksort example, is that list-sorting is a case where you definitely care more about the how than the what.

-------------------

EDIT, since two people called me out on it: It was an overstatement on my part to say that it's "precisely visible" what your Java code will translate to, but to suggest the two languages have the same degree of abstraction from the CPU is ridiculous. The code translation from Java to bytecode is quite straightforward, because most of the optimization occurs at runtime with JIT. There is a reasonably direct relationship between the code you write, the bytecode it gets translated into, and the instructions executed at runtime. At the end of the day, Java code consists of a series of instructions for the computer to follow, while on the other hand in Haskell, you aren't even technically giving instructions at all -- you're just writing equations. Compiled Haskell code is completely inscrutable.

Also, I should note that I am an enthusiastic Haskell hobbyist, and write it on almost a daily basis. Although I might not come across it here, I am a huge fan of the language; outside of the languages I use at work, by far the one I use most is haskell.

Re: Programming and thinking the functional way

#20

It boils down to the choice between these two alternatives: 1) If it's simple to imagine the computer doing something, it should be easy to program. 2) If it's simple to analyze something mathematically, it should be easy to program. The first path leads to C-style programming with pointers and loops. The second path leads to lazy pure functional programming and beyond. Personally, I'm in the first camp. Small functi…

> Maybe that just says something about my intelligence, or maybe the functional camp hasn't yet figured out how to write large programs in a readable way.

You make it sound like we've figured out how to write imperative large programs in a readable way.

Post reply on HN