On Github damianfral / slides-functional-programming-coffeescript
Transforming a function that receives multiple arguments into a function that receives only one argument:
# ((a, b) -> c) -> a -> b -> c
curry = (f) ->
    (a) ->
        (b) ->
            f(a,b)
_add = (x,y) -> x + y
add  = curry _add
add(2)(3) # ==> 5
add7 = add 7
add7 10  # ==> 17
Writting pure higher order curried functions in CoffeeScript is easy and powefull:
map = (f) ->
    (list) ->
        return (f x for x in list)
map(add7)([1, 2, 3]) # ==> [ 9, 10, 12 ]
filter = (f) ->
    (list) ->
        result = []
        for x in list
            result.push x if f x
        return result
odd = (num) -> num % 2
filter(odd)([1..10]) # ==> [ 1, 3, 5, 7, 9 ]
fold = (f) ->
    (init) ->
        acc = init
        (list) ->
            acc = f(acc)(x) for x in list
            return acc
sum = fold(add)(0)
sum [1..43] # ==> 946
mult    = (x) -> (y) -> x * y
product = fold(mult)(1)
factorial = (x) -> product [1...x]
factorial 6 # => 120
f : B --> C g : A --> B f . g : A --> C
negate = (bool) -> ! bool odd = (num) -> num % 2 even = compose(negate)(odd)
comp = (f) ->
    (g) ->
        (args...) ->
            return f(g.apply @, args)
head = (list) -> list[0]
tail = (list) -> list[1..]
fold1 = (fn) ->
    (list) ->
        fold(fn)(head list)(tail list)
compose = fold1(comp)
# Naive example
bestStudent = compose [head, (sortBy meanQualification), (filter hasPassedAllExames)]
mostCommon [1,7,200,6,3,7,7,999,1,44] # ==> 7 mostCommon 'functional programming!' # ==> 'n'
compare = (x) ->
    (y) ->
        return  1 if x > y
        return -1 if x < y
        return  0
equal  = (x) -> (y) -> x is y
negate = (bool) -> ! bool
maxBy = (fn) ->
    (x) ->
        (y) ->
            return y if fn(x)(y) is -1
            return x
maximumBy = (fn) ->
        fold1(maxBy(fn))
reject = (fn) ->
    return filter(compose [negate, fn])
split = (fn) ->
    (list) ->
        fullfilled  = filter(fn)(list)
        rejected    = reject(fn)(list)
        return [fullfilled, rejected]
groupBy = (fn) ->
    (list) ->
        return [] unless list.length
        x        = head list
        xs       = tail list
        [ys, zs] = split(fn x)(xs)
        # Recursion
        return [[x].concat(ys)].concat(groupBy(fn)(zs))
group = groupBy equal
group [6,7,8,6,7,8,9,1] # [ [ 6, 6 ], [ 7, 7 ], [ 8, 8 ], [ 9 ], [ 1 ] ]
length        = (list)  -> list.length
compareLength = (list1) ->
    (list2) ->
        compare(length list1)(length list2)
mostCommon = compose [head, (maximumBy compareLength), group]
mostCommon [1,7,200,6,3,7,7,999,1,44] # ==>  7
mostCommon 'functional programming'   # ==> 'n'