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
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