Intro to Functional Programming Workshop (code4lib)

Post on 06-May-2015

2.904 views 0 download

Transcript of Intro to Functional Programming Workshop (code4lib)

var λ;Introduction to Functional Programming 

with JavaScript(and a little Haskell)

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

Rules for Today

λ

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]

Recursion!

"If you already know what recursion is, just remember the answer. Otherwise, find someone who is standing closer to Douglas Hofstadter than you are; then ask him or her what recursion is."

-- Andrew Plotkin

Exercise set 1a

10 minutes

Answers to set 1a

problem 1

var fact = function(x) {    return(       (x===1) ? 1 :       x*fact(x-1)       );}

function fact (x) {     if(x==1){            return 1;      } else {        return x*fact2(x-1);      }}

problem 2

var fib = function(x){    return(          (x==0) ? 0 :          (x==1) ? 1 :          fib(x-1)+fib(x-2)    );

}

problem 2 continued...

var fib_answers = []fib_answers[0] = 0;fib_answers[1] = 1;var fibm = function (x) {     return fib_mem(x,fib_answer);}

var fib_mem = function(x,m){    if(m[x] != undefined){         return m[x];    } else {         m[x] = fib_mem(x-1,m)+fib_mem(x-2,m);         return m[x];    }}

problem 2 last one I swear (also very functional)...

var fib3wrapper = function(c){    return fib3(c,1,0);}

var fib3 = function(c,last1,last2){     return(            (c==2) ? last1+last2:            fib3(c-1,last1+last2,last1)     );}

Exercise set 1b

10 minutes

Answers to set 1b

problem 1

var length = function (xs) {     return(          empty(xs) ? 0 :          1 + length(rest(xs))     );};

problem 2

var nth = function(n,xs){    return(         empty(xs) ? [] :         (n == 0) ? first(xs) :         nth(n-1, rest(xs))    );

};

problem 3

var removeAll = function (x, xs) {    return(        empty(xs) ? [ ] :        (x == first(xs)) ? removeAll(x,                                    rest(xs)) :        build(first(xs),               removeAll(x,rest(xs)))

    );};

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

Lambda Functions

http://www.flickr.com/photos/jeremymates/2362399109/

Lambda Function (Haskell)

add4 = (\x -> 4+x)

>argIs2((\x -> 4+x))6

Lambda Function (JavaScript)

$.ajax({ url: "test.html", context: document.body, success: function(){        $(this).addClass("done");      }});

$("#exec").click(function(){  $("#results").prepend("<li>Normal Handler</li>");});

Exercise set 2

10 minutes

Answers to set 2

problem 1

var argIs2 = function(func) {    return func(2);}

problem 2

argIs2(function(x){ add(2,x);} );

problem 3

var flip = function (func) {       return(                 function(x,y){                         func(y,x);                 }       );};

Break!

5 minutes

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

Exercise set 3

5 minutes

Answers to set 3

problem 1

var makeAdder = function (x) {    return(        function(y) {                  return add(x,y);              }    );};

problem 2

var apiClosure = function(apiKey){    return(        function(x){             return apiSearch(apiKey,x);        }    );};

problem 3

var compose = function (f1,f2) {    return(         function(x){             f1(f2(x));         }    );};

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)

Exercise set 4a

5 minutes

Answers to set 4a

problem 1

var map = function (func, xs) {    return(        empty(xs) ? [ ] :        build( func(first(xs)),                  map (func, rest (xs))));    );};

problem 2

map(function(x){                return x*x},         xs);

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]

Exercise set 4b

10 minutes

Answers to set 4b

problem 1

var filter = function (test,xs){    return(         empty(xs) ? [ ] :         test(first(xs)) ? filter(test, rest(xs)) :         build(first(xs),filter(test,rest(xs)))    );};

problem 2

var removeAll = function(x,xs){    return(        filter(function(y){                          return y == x},                 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 xssumOfSquares xs = foldl (+) 0 (map (^2) xs)sumOfSquaresv2 = (mySum . squareAll)

> mySum [1..2000000]2000001000000> 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]

Exercise set 4c

5 minutes

Answers to set 4c

problem 1

var foldl = function (step, init, xs) {    return(         empty(xs) ? init  :        foldl(step,                step(init,first(xs)),                rest(xs)

    );};

problem 2

var sum = function(xs) {    return foldl(add,0,xs);};

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

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

Break

5 minutes

Exercise 5a

5 minutes

Answers to set 5a

problem 1

var last = compose(first,reverse);

problem 2

var reverse = function (xs) {    return foldl(flip(build),[ ],xs);};

Standard Deviation

1. calculate the arithmetic mean of the list2. 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 Deviation

1. calculate the arithmetic mean of the list

mean xs = sum xs / fromIntegral(length xs)2. subtract the mean from all the numbers in the list

deviations xs = map (\x -> x - m ) xs                where m = mean xs3. square the numbers in that list

squareDeviations xs = map(^2) devs                      where devs = deviations xs4. calculate the sum of the list

sumSquareDeviations xs = (sum .squareDeviations) xs5. divide the sum by length of list minus 16. get the square root of this number 

sd xs = sqrt $ sumSqDev / lsub1 where sumSqDev = sumSquareDeviations xs       lsub1 = fromIntegral $ ((-1+) . length)xs

Exercise 5b

10 minutes

Answers to set 5b

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)/(length(xs)-1)));};

Standard Deviation

Haskell> sd [1,4,5,9,2,10]3.65604522218567

JavaScript> sd([1,4,5,9,2,10]);3.65604522218567

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

Exercise 6

10 minutes

Answers to set 6

problem 1

var makeAdder = curry(add,x);

var apiClosure = curry(apiSearch,apiKey);

problem 2

var unrealisticFunction = function (a, b){    (function(c){        return((function(d){                                if(c<d){                                           return c+d;                                           }else{                                           return c*d;                                          }                    };)(c+a)        );    })(a*b)};

Thanks!

email: wckurt@gmail.com

twitter: willkurt

Still have time?

awesome!

Haskell vs JavaScript

Types!!!

areaOfTrapezoid :: Float -> Float -> Float -> FloatareaOfTrapezoid h b1 b2 = 0.5*h*(b1+b2)

evenList :: (Integral a) => [a] -> [a]evenList xs  = filter even xs

Lazy Evaluation!!!

 [2,4..] !! 108> 218

Pattern MatchingpatternMatch [a,b,c] = b ++ c ++ apatternMatch [a,b] = a ++ bpatternMatch [] = "no list"patternMatch as = "a larger list"

Pattern MatchingpatternMatch ["a","b","c"]>"bca"patternMatch ["a","b"]>"ab"patternMatch [ ]>"no list"patternMatch ["a","b","c","d"]>"a larger list"

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