Introduction to Functional Programming
with Haskell and JavaScriptWill Kurt
Will Kurt, Creative Commons Attribution-ShareAlike 3.0
"A language that doesn't effect how you think about
programming is not worth learning"
--Alan Perlis
So what is Functional Programming?
http://www.flickr.com/photos/foundphotoslj/466713478/
What does this mean?
http://www.flickr.com/photos/61417318@N00/4908148942/
No Side Effects!
http://www.flickr.com/photos/rka/1733453/
http://www.flickr.com/photos/23912576@N05/3056871500/
Haskell!
http://www.flickr.com/photos/micurs/4870514382/
JavaScript!!!
http://www.flickr.com/photos/jurvetson/96972777/
Lists!!!
first [1,2,3,4] -> 1 (aka: car, head)
rest [1,2,3,4] -> [2,3,4] (aka: cdr, tail)
empty [1,2,3,4] -> false (aka: null?, nil? empty?,[])
empty [] -> true
build 1 , [2,3,4] -> [1,2,3,4] (aka: cons, ':' )
build [1] , [2,3,4] -> [[1],2,3,4]
First class functions
http://www.flickr.com/photos/richardmoross/2211308689/
First Class Functions (Haskell)add2 x = 2 + xadd3 x = 3 + x
> add2 57
> add3 58
First Class Functions (Haskell)argIs2 func = (func) 2argIs3 func = (func) 3
> argIs2(add2)4> argIs2(add3)5> argIs3(add2)5> argIs3(add3)6
First Class Functions (JavaScript)
function argIs2(func){ return func(2);}function argIs3(func){ return func(3);}
Lambda Functions
http://www.flickr.com/photos/jeremymates/2362399109/
Lambda Function (Haskell)
add4 = (\x -> 4+x)
>argIs2((\x -> 4+x))6
Lambda Function (JavaScript)
var add4 = function(x){ return x+2;}
var example = argIs2(function(x){return x+2});
var exampple2 = argIs2(function(x){return x+1000});
Lambda Function (JavaScript)
$.ajax({ url: "test.html", context: document.body, success: function(){ $(this).addClass("done"); }});
$("#exec").click(function(){ $("#results").prepend("<li>Normal Handler</li>");});
Closures
http://www.flickr.com/photos/theredproject/3431459572/
Closures (Haskell)
add5 = (+5)makeAdder val = (+val)makeAdderWithLambda val = (\x->x+val)
add6 = makeAdder 6add7 = makeAdderWithLambda 7
> add5 510> add6 511> add7 512
Closures (JavaScript)
var makeAdder = function(val){ return(function(x){ return val+x; } );};
>var add6 = makeAdder(6);>add6(5);11>add6(8);14
Higher Order Functions
http://www.flickr.com/photos/73416633@N00/2425022159/
Map
http://www.flickr.com/photos/rosenkranz/3052214847/
Map (Haskell)
doubleAll xs = map (*2) xssquareAll xs = map (^2) xssquareAndAdd xs = map (\x->x*x+x) xsupperCase s = map toUpper s
> doubleAll [1,2,3,4][2,4,6,8]> squareAll [1,2,3,4][1,4,9,16]> squareAndAdd [1,2,3,4][2,6,12,20]> upperCase "doggie""DOGGIE"
Map (Haskell)
doubleAllv2 = map (*2)squareAllv2 = map (^2)squareAndAddv2 = map (\x->x*x+x)
Map (JavaScript) 'The Spolsky Map'
function spolsky_map(fn, a) { for (i = 0; i < a.length; i++) { a[i] = fn(a[i]); } }
note the side effects
Map (JavaScript) Purely functional version
var map = function (func,xs) { return (empty(xs) ? [] :build(func(first(xs)), map(func,rest(xs))));
};
note: xs and the returned list are distinct
Filter
Filter (Haskell)
evenList xs = filter even xsmod17list xs = filter (== (`mod` 17) 0) xsdoubleEvens xs = (doubleAll . evenList) xs
> evenList [1,2,3,4,5,6][2,4,6]> mod17list [1..100][17,34,51,68,85]> doubleEvens [0,3..27][0,12,24,36,48]
Filter (JavaScript)
var filter = function (test,xs) { return (empty(xs) ? []:test(first(xs)) ? build(first(xs), filter(test,rest(xs))) : filter(test,rest(xs))); };
Foldl (Reduce)
http://en.wikipedia.org/wiki/File:Sermon_in_the_Deer_Park_depicted_at_Wat_Chedi_Liem-KayEss-1.jpeg
Foldl (Haskell)
mySum xs = foldl (+) 0 xsmyReverse xs = foldl (\x y -> y:x) [] xssumOfSquares xs = foldl (+) 0 (map (^2) xs)sumOfSquaresv2 = (mySum . squareAll)
> mySum [1..2000000]2000001000000> myReverse [4,16..200][196,184,172,160,148,136,124,112,100,88,76,64,52,40,28,16,4]> sumOfSquares [1..10]385> sumOfSquaresv2 [1..10]385
Foldl (Haskell)
myReverse xs = foldl (\x y -> y:x) [] xsmyReverse [1,2,3]
foldl (\x y -> y:x) [] [1,2,3]
.. (\[] 1 -> 1:[]) .. => [1]
foldl (\x y -> y:x) [1] [2,3]
.. (\[1] 2 -> 2:[1]) .. => [2,1]
The Spolsky Reduce (foldl)
function spolsky_reduce(fn, a, init) { var s = init; for (i = 0; i < a.length; i++) s = fn( s, a[i] ); return s; }
Foldl (JavaScript) Purely Functional
var foldl = function (fn, init, xs) { return( empty(xs) ? init: foldl(fn, fn(init, first(xs)), rest(xs)) );};
Function Currying
Currying (Haskell)
myAdd x y = x + yadd8 = myAdd 8add9 = (+9)
> myAdd 8 917> add8 917> add9 817
Currying (JavaScript)
var curry = function (f,a) { return(function(){ var args = Array.prototype.slice.call(arguments); args.unshift(a); return f.apply(this, args);} );};
Currying (JavaScript) purely functional
var curry = function (f,a) { return(function(){ return((function(args){ return f.apply(this, build(a,args));})(Array.prototype.slice.call(arguments)) );} );};
Currying (JavaScript)
var add_three = function(a,b,c){ return a+b+c;};
>f1 = curry(add_three,1);>f1(2,3)6
>f2 = curry(curry(add_three,1),2);>f2(3)6
Standard Deviation
1. calculate the arithmetic mean of the list
2. subtract the mean from all the numbers in the list3. square the number in that list4. calculate the sum of the list5. divide the sum by length of list by 16. get the square root of this number
Standard Deviation1. calculate the arithmetic mean of the listmean xs = sum xs / fromIntegral(length xs)2. subtract the mean from all the numbers in the listdeviations xs = map (\x -> x - m ) xs where m = mean xs3. square the numbers in that listsquareDeviations xs = map(^2) devs where devs = deviations xs4. calculate the sum of the listsumSquareDeviations xs = (sum .squareDeviations) xs5. divide the sum by length of list by 16. get the square root of this number sd xs = sqrt $ sumSqDev / lsub1 where sumSqDev = sumSquareDeviations xs lsub1 = fromIntegral $ ((-1+) . length)xs
Standard Deviation (JavaScript)
var mean = function (xs){ return(sum(xs)/flength(xs));};
var deviations = function (xs) { var m = mean(xs);//we can remove this return map(function(x){return x-m;},xs);};
var squareDeviations = function(xs){ return map(square,deviations(xs));};
Standard Deviation (JavaScript)
var sumSqDeviations = compose(sum,squareDeviations);
var sd = function(xs){ return Math.sqrt( (sumSqDeviations(xs)/(flength(xs)-1)));};
Standard Deviation
Haskell> sd [1,4,5,9,2,10]3.65604522218567
JavaScript> sd([1,4,5,9,2,10]);3.65604522218567
Who actually uses this stuff?
http://cufp.org/
Ocaml
more @ http://www.scala-lang.org/node/1658
Haskell
... continued
more @ http://haskell.org/haskellwiki/Haskell_in_industry
Top Related