Hacker News new | past | comments | ask | show | jobs | submit login
Haskell: It’s like Klingon, but with math (sdtimes.com)
37 points by iamelgringo on April 16, 2009 | hide | past | favorite | 27 comments



I can definitely say that Klingon isn't a language you can just jump into. Er... I mean Haskell.

However, being the first functional language I'm really starting to grok I'm amazed at how powerful and concise it is.

Wasn't it Eric S. Raymond that told us we should all learn at least one functional language (namely lisp) in our lives not necessarily to program in, but to make us a better programmers?


Not just concise, but also readable. An example: translate lists into 'english text' lists. That is ["Apples"] -> "Apples", ["Apples", "Oranges"] -> "Apples and Oranges", ["Apples", "Oranges", "Pears"] -> "Apples, Oranges and Pears", etc.

(Problem a slight modification of the one described here: http://blogs.msdn.com/ericlippert/archive/2009/04/15/comma-q... )

The haskell solution:

    englishList [] = ""
    englishList [only] = only
    englishList [first,last] = first ++ " and " ++ last
    englishList (first:rest) = first ++ ", " ++ (englishList rest)
It's short, but completely readable. Compare that to the solutions given in the blog comments.


In the interest of comparing, using your simplification, here's a Smalltalk version...

    englishList: aList 
        ^ aList size > 2 
            ifFalse: [ aList join: ' and ' ]
            ifTrue: [ (aList allButLast join: ',') , ' and ' , aList last ]


In Ruby:

  def englishlist(array)
    array[0..-2].join(', ').to_s + (array.size > 1 ? ' and ' : '') + array.last.to_s
  end
(Not claiming it's as clear to read, but I miss my old one-liner contests! ;)

You can implement it roughly as clearly (although not as efficiently) as such:

  def englishlist(array)
    case array.length
      when 0; ""
      when 1; array.first
      when 2; array.join(' and ')
      else; array.first + ', ' + englishlist(array[1..-1])
    end
  end
I do love me the Haskell so far, but I'm only into the basics still. Love pattern matching, was one of my favorite aspects of Erlang.


Ok, I'll be the nudge and say I don't understand the point. I never "got" this type of example from the lispers using destructuring and recursion on simple examples either.

This (and others) has a fairly obvious and equally readable counterpart in C++ (or any other imperative language, really), but there's a reason why one doesn't implement it this way in those languages -- and a reason why (some of) the examples given have a certain bias towards iteration.

Wouldn't the same reason hold in haskell? Or do we care about runtime efficiency at all?


The Haskell example compiles to an iterative version, as far as I'm aware.


It complies to neither an iterative NOR a recursive version. It compiles to LAZY version. This code doesn't loop at all. It forces the argument just deep enough to go three nodes into the list spine. Then, picks the branch based on the number items in the list, forces the first element of the list, and sets up a thunk for appending everything on later.

This was a little bit of a simplification of things; I don't need to go into great detail to make my point.


Okay, but in doing so, it's not pushing an extra stack frame with each step, but rather just jmping its way along, correct? That's what most people think of as being iterative (or tail-recursive), rather than simply recursive, behaviour, and it can apply equally to a lazy algorithm.


No, you can't simply apply that analysis to lazy algorithms. foldr is not a tail-recursive function in a strict language. However, in a lazy language, foldr may not push O(n) frames on the stack.

The code you are looking at here is NOT tail-recursive. Haskell's implementation of ++, in a strict language, will always push O(n) frames on the stack.

But it IS true that this code is O(1) in stack consumption with Haskell's execution model.


Yes, it can apply. Developing an intuition for when Haskell produces strict code and when the compiler is not smart enough to remove the lazyness, helps tremendously in programming bigger programs. I am still in the process of acquiring said intuition.


I think the point is, recursive solutions like the above are often easier to read.

In fact the example above looks tail-recursive to me (at least if you add in an accumulator parameter). That means a good compiler will make it efficient.


Note though that using ++ like that builds lots and lots of intermediate lists.


Yeah but to be fair he said you should learn a decent language from all paradigms, things like Smalltalk, Haskell, Prolog, C etc. and not specifically functional programming. He was quite specific about learning Lisp though, probably because of the metaprogramming aspect.


I think it was probably more the functional programming. You can do metaprogramming even in PHP.


You can do meta programming in Assembly too, but it is much more common in Lisp.


Right, but I meant generating code at compile time with macros which take code as a data structure as their input. PHP doesn't have that.


I've always found that attitude slightly strange. Having expended a lot of time and effort learning a functional language, why not program in it?


Because sometimes it isn't right for the job? Haskell is absolutely awesome for some things (probably quite a lot of things in fact) but for some other things it's maybe not optimal.

It's a lot of fun though, and if even it does nothing but stretch your mind to some new ways of doing things then it's very much worth learning.


Sometimes is a long way from never. The relevant phrase here is "not to program in"; you clearly agree with me that this is a mistaken attitude.


I meant "not necessarily to program in". E.g. it's not going to be something you use all the time. The sad fact is that a lot of existing code and companies use fairly safe languages like C and Java, but simply knowing how to think about functional programming will help you out with all your programming, no matter the language.


I'm curious why you consider C to be safe but Haskell not. Seeing as C has no bounds checking on arrays, runtime type-checking, or garbage collection, I'm tempted to argue to the contrary.


I'm guessing that Periodic means "safe" in terms of popularity and visibility, not ease of programming.


Do it every chance you get! It's just that you can't always program with a fun functional language.

The hardest part is in collaboration with people who have been using C for 10+ years and aren't interested in other things. Fortunately we have standards for linking object files together independent of their source language.


Yes. And still you have to live with their restrictions e.g. cope with manual memory management, at least on the interface to C.


Not to mention the impossibility of learning a language without actually programming in it.


I know this comment is totally off-topic, but that headline is absolutely killer!

Good article too!


Is one of the best titles I read today!




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

Search: