Hacker News new | past | comments | ask | show | jobs | submit login
Haskell One Liners to Impress Your Friends (fogus.me)
52 points by mmphosis on June 4, 2011 | hide | past | favorite | 18 comments



Trying to look at this from the perspective of someone who doesn't know Haskell, most of these aren't impressive, but in fact advertisements against Haskell.

First, consider that 6 of them are essentially applying a builtin function. That you can sum a list with the function

    sum [1..10]
is not impressive, it at best speaks to what functions the language designers thought to include. Similarly,

    partition (>60) [49, 58, 76, 82, 88, 90]
might be impressive to someone who has never seen first class functions (though they'd probably ascribe it to syntactic tricks), I think most programmers who are considering learning Haskell would say "Oh, hey, there's a builtin partition function. How nice."

On the other hand, there would be a lot of worrying features from these examples. Consider

    let fileLines = fmap lines $ readFile "data.txt"
What is fmap and how is it similar or different from map? Why not just "lines $ readFile ..." (assuming you find $ notation readable, which you'd probably pick up on fairly quickly)? Why, in the birthday example, do we use mapM_? How are map, fmap, mapM_, and presumably some hypothetical mapM, related? because the use of mapM_ seems identical to map, and fmap looks completely unrelated. What is foldl1, and how is it different from foldl?

In the same vein, why are there liftM calls all over that one example which says "I have curl and xml parsing as libraries"? Or, in the alternate form of that example, what is <$> and how is it different from <$>? Because it looks the same, but not quite, since it forces the left $ to become ., not <$>...

Overall, the only one of these that would have looked interesting to me two years ago, when I programmed exclusively in Python, would be the last two, and even so, the last one mostly looks like, "hey, we have list comprehensions that are better somehow" and the one before that looks like "hey, we have a concurrency library".

What makes a good advertisement for a language? "I have the following functions built in" doesn't work. You need to demonstrate some core language features that work in a large number of cases. Yes, you have a "sum" function. But that tells me nothing if I want a standard deviation, unless you have that built in too. If, instead, you demonstrated a list comprehension, I might say, "Oh hey, I could use that pattern a lot". If I'm advertising Python, I might show off the fact that for loops loop over iterators, that objects are dynamically typed (with, say, file-like objects), decorators, and other examples where the language provides general structure to build upon.

So if you want to advertise Haskell, why not show some simple monad in action that stresses that it's a general pattern of abstracting computation (or, say, demonstrate writing your own data structure and then using fmap on it), show an infinite list, maybe note that you can transparently compile in concurrency. These aren't well-thought-out suggestions, but look, the Fibonacci example is something that might excite a Python (say) or Java programmer (I remember first reading about generators and being astounded!) far more than "Look, XML parsing and Curl in my libraries! Ignore the liftMs!"

Point being, if the function is already written, any operation is a one-liner. So you better either be claiming that all functions have been written in your language (the "batteries included" ad slogan) or that the language provides some way of building up its few functions to do whatever you want, easily. "Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary," they say. This blog post shows me 10 features, and also what appear to be quite a few structural weaknesses. I'm not impressed.


This "10 one liners.." is the third or fourth one this week; so I think it's just a way to say "Heh, your favorite language can do that? Mine too, here's how".

I wanted to show a "Impress your friend with python" suite but would not be shy to use 3-4 lines and make it easy to read and finish the article with: "Don't impress your friend, code in a way that you'll keep them!" ;-)


> might be impressive to someone who has never seen first class functions (though they'd probably ascribe it to syntactic tricks)

It's not just using first-class functions here, it's partially applying a flipped curried operator. That's not exactly common.


Flipped curried operator? You mean like this:

  (defn flip-arguments
    [func]

    (fn [& args]
      (apply func (reverse args))))

  (prn (partition-by (partial (flip-arguments <) 60) [49 58 76 82 88 90]))
I noticed Haskell does automatic currying. You can easily create that or basically any other language feature using Lisp macros:

  (defn currify
    [f n]

    (fn [arg]
      (if (= n 1)
	(f arg)
	(currify (partial f arg) (dec n)))))

  (defmacro currying-function
    [arg-names & code-args]

    `(currify (fn ~arg-names ~@code-args) ~(count arg-names)))

  (def gt (currying-function [a b] (> a b)))
Once you experience the power of Lisp macros it is hard to go back to non-homoiconic languages such as Haskell that hide the underlying structure of the code.

I am not impressed by the Haskell code shown here, flipping and currying are feature Lisps had back in the 1980s or earlier, before Haskell was born.

Actually, I find the Haskell code rather revolting. First of all because of the horrid camel-case names (isInfixOf, parseXMLDoc, curlGetString, etc) then there is the very confusing syntactic constructs, like $ and <$>, and hard to interpret names like map, fmap, mapM_, foldl, and foldl1.


My personal favourite Haskell one-liner is using scan for the fibonacci sequence:

fibs = 1 : scanl (+) 1 fibs


Or

> fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

Which IMO is easier to grasp intuitively.


Could you explain what it does?


scan is similar to fold - except instead of the result being the final value, it's a list of all the intermediate values up to the final one (if it exists - scanl is productive and can handle infinite lists just fine).

So the first fibonacci number is 1 (we're concatenating it onto the front of the list), the second fibonacci number is also one (the second argument to scan), and every fibonacci number after that is the sum of the previous number (scan's running total) and the one before that.



>any (flip isInfixOf tweet) wordlist

Even shorter: any (`isInfixOf`tweet) wordlist

Partial application of infix operators automatically adds flip if needed.


Without knowing what's included in the core of the language and what comes as constructs on top of it, it is hard to get impressed with these examples.

I see them as an equivalent of giving STL-heavy examples when trying to impress someone with C++ - "Look! Sorting an array with one function call - std::sort(head, tail) !"


Meh, most of them are not traditional one-liners in the sense that you can actually do something with in- and output in just that one line.

They require you to actually have data in Haskell structures, and those that don't aren't one-liners.


  powerset = filterM $ const [True, False]


I'm surprised this is missing the canonical quicksort in one line of Haskell


But the 'canonical quicksort' is not quicksort ;), just a slow look-alike:

http://augustss.blogspot.com/2007/08/quicksort-in-haskell-qu...


No, it's quicksort. It's just not the best implementation of quicksort.


No, it's not. First line of Hoare's 1962 paper describing quicksort:

A description is given of a new method of sorting in the random access store of a computer

The paper also emphasizes the use of in-place mutations in quicksort. The qsort one-liner uses lists, which are not random-access and cannot be modified in-place.


It's because this post is part of a meme: someone wrote a post with precisely this list of 10 one liners in some language (Scala, I think) and then several others have written translations to other languages.




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

Search: