How learning Haskell changed my view on ES6 and got me into spidermonkey development

It all started with an idea:

I want to learn a "brutally pure"

functional programming language

Contenders:

  •  Haskell
  •  Scheme (or any other LISP)

  • I didn’t really consider erlang, not sure why

Scheme

(define factorial 
  (lambda (n) 
    (if (= n 0) 
        1  
        (* n (factorial (- n 1)))
     )
  )
)

Haskell

factorial 0 = 1
factorial n | n > 0 = n * factorial (n - 1)

Prefix/infix notation

Scheme/LISP has prefix notation for everything:

`operator operand1 operand2`

`+ 1 2 // = 3`

almost *everyone else* uses infix notation:

`operand1 operator operand2`

`1 + 2 // = 3`

But there is some logic behind it

essentially every operator is a function

`fncall parameter1 parameter2`

or for c-style languages:

`fncall(parameter1, parameter2)`

You can use both in Haskell

using operator as function (prefix):

`(+) 1 2`

using function as operator (infix):

`1 `fn` 2`

(those are backticks)

I can’t just learn a new language without a use-case

http://contest.catalysts.cc/

participated a few times already,

problems are a good fit for functional programming (i think)


so i started learning Haskell and solve some of the older exercises with it.

I didn’t actually use Haskell


I made good progress learning it

but it just wasn’t enough to participate in the CCC


so i fell back to JS

but with a twist

Lets focus on these areas:

  • functions / invocation / application (some delicious curry)
  • pattern matching / destructuring
  • lazyness / generators (you know I love those :-)

Functions in Haskell


`fnname arg1 arg2 arg3`

functions can be partially applied

("currying" in functional programming speak)


theoretically, a function has a single argument and a single return value; everything else is just syntactic sugar

Optional function signatures

`map :: (a -> b) -> [a] -> [b] `

or make it more clear:

`map :: (a -> b) -> ([a] -> [b])`


`fn a b c = a + b + c`

with signature:

`fn :: a -> b -> c -> d`

or more clearly:

`fn :: a -> (b -> (c -> d))`


partial application

`map fn` -> ([a] -> [b])


`plusone = map (+1)`


`plusone [1,2,3]` == [2,3,4]

in ES6?

Arrow functions! \o/


`var map = fn => it => [for (x of it) fn(x)];`


`var plusone = map(x => x+1);`


`plusone([1,2,3])` == [2,3,4]

Pattern matching

Haskell has lists and tuples

lists = variable-length array of same-type objects

tuples = fixed-length "array" of objects with given type

(like a C struct, but without names)


syntactic sugar:

[1,2,3] == 1:2:3 == (1:(2:(3:[])))




Pattern matching (2)

`sum [] = 0`

`sum (first:rest) = first + sum rest`


`also (first:second:third:rest) = …`


`getName (name, address, birthday) = name`

that are not separate parameters, that’s a single tuple with 3 values!

In ES6?

destructuring assignment! \o/


`var [first, second, ...rest] = iterable;`

`var {propa, propb: localb} = object;`

also elsewhere:

`for (var [key, value] of map.entries())`

`function ([first, ...argrest], {propa}, ...fnrest)`

`catch ({name, message})`

Lazyness

I’m probably the laziest person you will know :-)


everything in Haskell is lazily evaluated

[1..] Infinite lists,

recursion, …


good for memory usage. only keep in memory what you really need. on the fly, streaming, …

IN ES6?

generators! \o/

function *nat() {
  var i = 0;
  while (true) yield i++;
}
generator expressions:
`var map = fn => it => (for (x of it) fn(x));`
`var filter = fn => it => (for (x of it) if (fn(it)) x);`

Some problems though:

`var [first, second, ...rest] = nat();`

works, but `rest` is evaluated eagerly :-(

can I use?

v8/chromium/node: only generators


spidermonkey/firefox: depends

destructuring rest (`[a, ...rest] = arr`) does not work

destructuring only works on arrays, not iterables


transpilers (traceur): depends

destructuring only works on arrays

What do I do when there is a bug?

I fix it!


Bug 933276 - (spread-assignment) Implement [...x] in assignment target (spread operator)

~20 hours of reading code, hacking and…


some refactoring…

a few iterations…

and broken tests…

… later

I’m blocked by another bug

and waiting for review…

BUt while I’m at it:

Bug 875002 - Allow shorthand properties in object literals


var a = 10;
var b = 20;
return {a, b};
… also waiting for review

Hopefully ready for Firefox 33

Takeaway?


Haskell opened my eyes to some functional programming sugar

(or might I say curry?)


ES6 makes a lot of those concepts work in JS

BUT: I’m still not as lazy as I wish I was :-D


Get on the ES6 bandwagon now!

If there is a missing feature, implement it yourself!

v8 needs a lot of love!

BUT

Haskell is still extremely hard…

IO / Monads anyone?


great learning experience

but I don’t use it actively anywhere

How learning Haskell changed my view on ES6 and got me

By Arpad Borsos

How learning Haskell changed my view on ES6 and got me

  • 2,598