Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've been using CoffeeScript for a while now. On Wikipedia, it is said that CoffeeScript is influenced by Haskell. But after I check out the syntax of Haskell, I have found little resemblance from CoffeeScript.

Which aspect of CoffeeScript is influenced by Haskell?

share|improve this question

migrated from stackoverflow.com Mar 14 '12 at 2:27

This question came from our site for professional and enthusiast programmers.

2  
On the Wikipedia page itself it says "In CoffeeScript, the function keyword is replaced by the -> symbol, and indentation is used instead of curly braces, as in Python and Haskell." Maybe that's it. –  Thilo Mar 14 '12 at 2:02
4  
Voted to move to Programmers –  Chris Laplante Mar 14 '12 at 2:16
4  
@DeadMG: I don't think the syntax is the "most irrelevant" (otherwise Scheme wouldn't be less popular than Python :P), but it isn't the most important either. –  Tikhon Jelvis Mar 14 '12 at 2:43
8  
Notice the [1] next to the sentence you're referring to? That's a link to the first of the references of the article, a podcast interview with Jeremy Ashkenas, the designer of CoffeeScript. Listen to the podcast, and your question will be answered... –  Yannis Rizos Mar 14 '12 at 2:44
8  
@DeadMG From a computer's perspective, yes, but not to humans! Failure to understand this is why we have XML. –  Pubby Mar 14 '12 at 7:10

4 Answers 4

up vote 10 down vote accepted

Coffeescript is a gateway drug for Haskell. Let's take a look at the Quicksort algorithm, as presented in Chapter Five of Learn You A Haskell For Great Good:

quicksort [] = []
quicksort (x:xs) =
       let smallerOrEqual = [a | a <- xs, a <= x]
           larger = [a | a <- xs, a > x]
       in quicksort smallerOrEqual ++ [x] ++ quicksort larger

And the equivalent in Coffeescript:

quicksort = (x) ->
    return [] if x.length == 0
    h = x.pop()
    smallerOrEqual = (a for a in x when a <= h)
    larger = (a for a in x when a > h)
    (quicksort smallerOrEqual).concat([h]).concat(quicksort larger)

The only obvious difference between these two bits of code is that the pattern had to be turned into a guard condition.

These are not equivalent pieces of code. The Haskell code will only do the list comprehensions lazily, i.e. when needed by the in line. Pattern recognition is a big deal in Haskell. Haskell will optimize this code with tail-recursion, whereas Coffeescript will just build a framestack as big as the number of recursions needed. And the Haskell version cares about the contents of the list and demands they be all of the same type, since Haskell is so strongly typed.

But one could be fooled, by their clear syntactical resemblence, into believing they were equivalent. And to some extent, a smart developer could use that resemblence to write Coffeescript that, if not lazy or strongly typed, was nonetheless better disciplined and more functional. Haskell is an excellent language for learning that discipline, and those skills are directly translatable to Coffeescript's syntax.

[EDIT] Building on Linus's excellent addition below, we can even simulate Haskell laziness:

quicksort = ([x, xs...]) ->
    return [] unless x?
    smallerOrEqual = -> (a for a in xs when a <= x)
    larger = -> (a for a in xs when a > x)
    (quicksort smallerOrEqual()).concat(x).concat(quicksort larger())

Now the two expressions only trigger when their results are needed, not just imperatively. I doubt this actually wins you anything, but it does seem to be getting closer to some Haskellian purity.

share|improve this answer

Building on Elf Sternberg's answer, you can actually make quicksort even a little more "Haskell-like" with Coffeescript's destructuring:

quicksort = ([x, xs...]) ->
  return [] unless x?
  smallerOrEqual = (a for a in xs when a <= x)
  larger = (a for a in xs when a > x)
  (quicksort smallerOrEqual).concat(x).concat(quicksort larger)

It's not quite pattern matching, but it's a little closer. ;-)

share|improve this answer
2  
I've used destructuring for objects (as hashes, for example), but haven't seen its use with arrays. Wow, that's very nice. I've learned something new. Thanks! –  Elf Sternberg Mar 16 '12 at 16:28

For me, CoffeeScript sometimes looks really similar to Erlang.

For example:

CoffeeScript:

f_qsort([]) -> []
f_qsort([Pivot, Rest...]) ->
  [
    f_qsort((X for X in Rest when X < Pivot))..., 
    Pivot, 
    f_qsort((Y for Y in Rest when Y >= Pivot))...
  ]

Erlang:

qsort([]) -> [];
qsort([Pivot|Rest]) ->
  qsort([ X || X <- Rest, X < Pivot]) 
  ++ [Pivot] ++ 
  qsort([ Y || Y <- Rest, Y >= Pivot]).

There is a library which provides a way to write Erlang-like constructions right in CoffeeScript without precompilation, just wrap up it in special function. You can find it here: https://github.com/nogizhopaboroda/f_context.

share|improve this answer

For me, the main difference is in function calls. In CoffeScript:

fun(bar(a, b, c))

or:

fun bar a, b, c

In Haskell:

fun $ bar a b c

or:

fun . bar $ a b c

Why oh why those commas between arguments.

Also the difference between quicksort (x:xs) = and quicksort = ([x, xs...]) -> is obvious, and confusing, because -> means something else in Haskell.

share|improve this answer
    
Question asks how CoffeeScript is influenced by Haskell, not syntactic differences –  Alex G Dec 9 at 12:02

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.