Functional Programming for OO Programmers (part 2)
-
Upload
calvin-cheng -
Category
Software
-
view
899 -
download
1
Transcript of Functional Programming for OO Programmers (part 2)
![Page 1: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/1.jpg)
FUNCTIONAL PROGRAMMINGfor OO programmers (Part 2)
![Page 2: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/2.jpg)
WHAT
• Pure versus Impure (exercise)
• Currying (exercise)
• Map, Filter, Reduce (exercise)
• Functors, Applicative Functors, Monads (exercise)
are we diving into?
![Page 3: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/3.jpg)
PURE OR IMPURErecognize pure functions
![Page 4: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/4.jpg)
RECOGNIZE
• Functions that don’t change anything out-of-scope and don’t depend on anything out-of-scope are called “pure”
• A pure function always gives the same result given the same parameters; independent of program/system state
pure functions
![Page 5: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/5.jpg)
RECOGNIZEpure function
var values = { a: 1 };
function pureFunction (a) {
var b = 1;
a = a * b + 2;
return a;
}
![Page 6: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/6.jpg)
RECOGNIZEimpure function
var values = { a: 1 };
function impureFunction (items) {
var b = 1;
items.a = items.a * b + 2;
return items;
}
![Page 7: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/7.jpg)
LET’S PLAYpure or impure?
![Page 8: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/8.jpg)
PURE OR IMPURE?function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) === variable) {
return decodeURIComponent(pair[1]);
}
}
}
![Page 9: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/9.jpg)
PURE OR IMPURE?function random(mZ, mW) {
mZ = 36969 * (mZ & 65535) + (mZ >> 16);
mW = 18000 * (mW & 65535) + (mW >> 16);
return (mZ >> 16) + mW;
}
![Page 10: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/10.jpg)
PURE OR IMPURE?function addAndShow(a, b, console) {
var c = a + b;
console.log(a, ' + ', b, ' = ', c);
return c;
};
![Page 11: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/11.jpg)
PURE OR IMPURE?var number = 1;
var increment = function() {
return number += 1;
};
increment();
![Page 12: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/12.jpg)
PURE OR IMPURE?var number = 1;
var incrementAlt = function(n) {
return n + 1;
};
incrementAlt(number);
![Page 13: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/13.jpg)
CURRYINGfirst-order function and higher-order function capabilities
![Page 14: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/14.jpg)
CURRYINGvar people = [
{ name: 'Calvin' },
{ name: 'John' },
{ name: 'Thomas' }
];
// function with hardcoded key 'name' to retrieve list of names
function getPersonName(obj) {
return obj['name'];
}
// mapping to the hardcoded function
var names = people.map(getPersonName);
console.log(names);
JavaScript
![Page 15: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/15.jpg)
CURRYING// Specify the key on-‐the-‐fly by using a generic function.
function getByKey(key, obj) {
return function(obj) {
return obj[key];
};
}
JavaScript
![Page 16: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/16.jpg)
CURRYINGfunction getByKey(key, obj) {
return function(obj) {
return obj[key];
};
}
var getByKeyPartial = getByKey('name');
console.log(getByKeyPartial);
var names2 = people.map(getByKeyPartial);
console.log(names2);
[Function]
curried function or partial function
JavaScript
![Page 17: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/17.jpg)
CURRYING
function getByKey(key, obj) {
return function(obj) {
return obj[key];
};
}
var names3 = people.map(getByKey('name'));
console.log(names3);
[Function]curried function or partial functionequivalent to:getByKey(‘name’)(obj) in this context
JavaScript
![Page 18: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/18.jpg)
CURRYINGmodule Main where
f :: Integer
f = max 4 5
fPartial :: (Ord a, Num a) => a -‐> a
fPartial = max 4
main :: IO ()
main = do
print f
let g = fPartial 10
print g
Haskell
![Page 19: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/19.jpg)
CURRYINGpeople :: [(String, String)]
people = [("name", "Calvin")
,("wat", "John")
,("name", "Thomas")
]
Haskell
![Page 20: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/20.jpg)
CURRYING{-‐ generic filterByKey function that accepts a string as
keyname and the data structure shown previously -‐}
filterByKey :: Eq a => a -‐> [(a, t)] -‐> [t]
filterByKey _ [] = []
filterByKey p ((k, v):xs)
| p == k = v : filterByKey p xs
| otherwise = filterByKey p xs
filterByName :: [(String, t)] -‐> [t]
filterByName = filterByKey "name"
Haskell
[Function]curried function or partial function
![Page 21: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/21.jpg)
CURRYINGmain :: IO ()
main = do
let names2 = filterByKey "name" people
print names2
let names3 = filterByName people
print names3
Haskell
[Function]curried function or partial function
![Page 22: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/22.jpg)
MAP, FILTER, REDUCELook ma, no loops
![Page 23: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/23.jpg)
MAP, FILTER, REDUCE// map, reduce and filter are built-‐in as methods of the
// Array class in JS
var aList = [0, 1, 2];
var newList = aList.map(function (i) {
return i + 1;
});
console.log(newList);
console.log(aList);
JavaScript map
![Page 24: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/24.jpg)
MAP, FILTER, REDUCEaList :: [Integer]
aList = [0, 1, 2]
addOne :: [Integer]
addOne = map (+1) aList
Haskell map
![Page 25: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/25.jpg)
MAP, FILTER, REDUCE// map, reduce and filter are built-‐in as methods of the
// Array class in JS
var aList = [0, 1, 2];
var lessThanTwo = aList.filter(function (i) {
return i < 2;
});
console.log(lessThanTwo);
console.log(aList);
JavaScript filter
![Page 26: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/26.jpg)
MAP, FILTER, REDUCEaList :: [Integer]
aList = [0, 1, 2]
lessThanTwo :: [Integer]
lessThanTwo = filter (<2) aList
Haskell filter
![Page 27: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/27.jpg)
MAP, FILTER, REDUCE// map, reduce and filter are built-‐in as methods of the
// Array class in JS
var aList = [0, 1, 2];
var reduceToSum = aList.reduce(function (a, b) {
return a + b;
});
console.log(reduceToSum);
console.log(aList);
reduce
![Page 28: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/28.jpg)
MAP, FILTER, REDUCEaList :: [Integer]
aList = [0, 1, 2]
reduceToSum :: Integer
reduceToSum = foldl (+) 0 aList
Haskell reduce (foldl and foldr)
![Page 29: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/29.jpg)
FUNCTORSa function that, given a value and a function, does the right thing
![Page 30: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/30.jpg)
FUNCTORSfunction addOne(value) {
return value + 1;
}
console.log(addOne(10)); // 11
function addTwo(value) {
return value + 2;
}
console.log(addTwo(10)); // 12
JavaScript
![Page 31: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/31.jpg)
FUNCTORS// A not-‐quite-‐there Functor
function aFunctor(value, fn) {
return fn(value);
}
console.log(aFunctor(10, addOne)); // 11, works as expected
console.log(aFunctor([1, 2, 3], addOne)); // '1,2,31' is
returned, which is not what we want
JavaScript
![Page 32: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/32.jpg)
FUNCTORSfunction betterFunctor(value, fn) {
if (typeof value === 'number') {
return fn(value);
} else {
var map = Array.prototype.map;
return map.call(value, fn);
}
}
JavaScript
![Page 33: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/33.jpg)
FUNCTORSconsole.log(betterFunctor([1, 2, 3], addOne)); // [2, 3,
4] is what we expected
console.log(betterFunctor(10, addOne)); // 11 is
what we expected
JavaScript
![Page 34: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/34.jpg)
FUNCTORS// JavaScript's Array's map method is a functor! :-‐)
var map = Array.prototype.map;
console.log(map.call([1, 2, 3], addOne)); // [2, 3,
4] is what we expected.
console.log([].map.call([1, 2, 3], addOne)); // This
works too
JavaScript
![Page 35: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/35.jpg)
FUNCTORSaddOne :: Num a => a -‐> a
addOne a = a + 1
addTwo :: Num a => a -‐> a
addTwo a = a + 2
result :: Num b => [b] -‐> [b]
result xs = map addOne xs
Haskell
![Page 36: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/36.jpg)
COMPARISONFunctors vs Applicative Functors vs Monads
Functors Applicatives Monads
example (+3) [2]== [5]
Just(+3) <*>
Just 2== Just 5
Just 4>>=
makeHalf== Just 2
examples functions map, fmap, <*> <*>, <$>, liftA2 >>=, liftM
brings function operator in
execute operationgeneralizedmap
does both <*> & <$>
apply fn to wrapped value
apply wrapped fn to wrapped value
apply fn that returns a wrapped value
to a wrapped value
![Page 37: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/37.jpg)
MAYBE FUNCTORSan often-used functor; and more about functors
![Page 38: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/38.jpg)
MAYBE FUNCTORS• Captures null check
• Value inside may or may not be there
• Maybe has two subclasses - ‘Just’ or ‘Nothing’ (Haskell)
• Also referred to as Option with subclasses ‘Some’ or ‘None’ (Scala)
• Also available in Swift, e.g. Optional, enum Either<NSError, User>
![Page 39: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/39.jpg)
MAYBE FUNCTORSvar aList = [1, 2, 3];
function compose(f, g) {
return function (x) {
return f(g(x));
};
}
function addOne(value) {
return value + 1;
}
function addTwo(value) {
return value + 2;
}
JavaScript
![Page 40: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/40.jpg)
MAYBE FUNCTORSconsole.log(aList.map(compose(addOne, addTwo)));
console.log(aList.map(addTwo).map(addOne));
function mayBe(value, fn) {
return value === null || value === undefined ? value :
fn(value);
}
JavaScript
![Page 41: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/41.jpg)
MAYBE FUNCTORSconsole.log(mayBe(undefined, compose(addOne, addTwo)));
// returns expected result undefined
console.log(mayBe(mayBe(undefined, addTwo), addOne));
// returns expected result undefined
console.log(mayBe(1, compose(addOne, addTwo)));
// returns expected result 4
console.log(mayBe(mayBe(1, addTwo), addOne));
// returns expected result 4
JavaScript
![Page 42: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/42.jpg)
MAYBE FUNCTORSaddOne :: Num a => a -‐> a
addOne a = a + 1
addTwo :: Num a => a -‐> a
addTwo a = a + 2
composedFn :: Integer -‐> Integer
composedFn = addOne . addTwo
res :: [Integer]
res = map composedFn aList
Haskell
![Page 43: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/43.jpg)
MAYBE FUNCTORSmain :: IO ()
main = do
print res
let res2 = fmap composedFn Nothing
print res2
let res3 = fmap composedFn (Just 1)
print res3
Haskell
![Page 44: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/44.jpg)
APPLICATIVESapply wrapped function to wrapped value
![Page 45: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/45.jpg)
APPLICATIVESvar none = {
map: function() {
return none;
},
bind: function() {
return none;
},
toString: function() {
return 'none';
}
};
JavaScript
![Page 46: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/46.jpg)
APPLICATIVESfunction some(value) {
return {
map: function(func) {
return some(func(value));
},
bind: function(func) {
return func(value);
},
toString: function() {
return "some(" + value + ")";
}
};
}
JavaScript
![Page 47: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/47.jpg)
APPLICATIVESvar functor = {
map: function(func, option) {
return option.map(func);
},
unit: some,
applyFunctor: function(funcOption, argOption) {
return funcOption.bind(function(func) {
return argOption.map(func);
});
}
};
JavaScript
![Page 48: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/48.jpg)
APPLICATIVESfunction curry(func, numberOfArguments) {
return function(value) {
if (numberOfArguments === 1) {
return func(value);
} else {
return curry(func.bind(null, value), numberOfArguments -‐ 1);
}
};
}
JavaScript
![Page 49: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/49.jpg)
APPLICATIVES// Usage
var four = some(4);
var six = some(6);
console.log(four.toString());
console.log(six.toString());
function add(a, b) {
return a + b;
}
var result = functor.applyFunctor(functor.map(curry(add, 2), four), six);
console.log(result.toString()); // some(10)
JavaScript
![Page 50: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/50.jpg)
APPLICATIVESresult = functor.applyFunctor(functor.map(curry(add, 2),
none), six);
console.log(result.toString());
result = functor.applyFunctor(functor.map(curry(add, 2),
four), none);
console.log(result.toString());
JavaScript
![Page 51: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/51.jpg)
APPLICATIVES// A cleaner API for our applicative functor operations
functor.applyFunctorUncurried = function(func) {
var args = Array.prototype.slice.call(arguments, 1);
return args.reduce(
functor.applyFunctor,
functor.unit(curry(func, args.length))
);
};
JavaScript
![Page 52: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/52.jpg)
APPLICATIVESvar result2 = functor.applyFunctorUncurried(add, four, six);
console.log(result2.toString());
result2 = functor.applyFunctorUncurried(add, none, six);
console.log(result2.toString());
result2 = functor.applyFunctorUncurried(add, four, none);
console.log(result2.toString());
JavaScript
![Page 53: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/53.jpg)
APPLICATIVESimport Control.Applicative
ans :: Maybe Integer
ans = (+) <$> Just 4 <*> Just 6
main :: IO ()
main = print ans
Haskell
![Page 54: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/54.jpg)
MONADSapply function that returns wrapped value to a wrapped value
![Page 55: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/55.jpg)
MONAD“A monad is just a monoid in the category of endofunctors, what's the problem?”
- James Iry (Brief, Incomplete and Mostly Wrong History of Programming Languages)
![Page 56: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/56.jpg)
MONADLet’s
• understand the why,
• then, illustrate the how
• and, we will know what a monad is.
![Page 57: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/57.jpg)
MONADWhy?
avoid mutable state while chaining a group of functions together (or executing a sequence of logic)
![Page 58: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/58.jpg)
MONADmutation:
functions in imperative languages change the state of values as logic is executed
![Page 59: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/59.jpg)
MONADSo what’s the big deal?
When data is mutable, parallel thread execution of your code on multiple CPUs leads to race conditions
Can’t do parallel thread execution on your multi-core machine ⇒
idle resource
If we insist on parallel thread execution without locks ⇒
unpredictable results, i.e. errors
![Page 60: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/60.jpg)
MONAD
![Page 61: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/61.jpg)
MONAD f (x)
x = g(x)
x = h(x)
x = i(x)
return x
![Page 62: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/62.jpg)
MONAD f (x)
x = g(x)
x = h(x)
x = i(x)
return x
x = 3
x = 5
x = 10
x = -3 x = -3
![Page 63: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/63.jpg)
f (x)
x = g(x)
x = h(x)
x = i(x)
return x
f (x)
x = g(x)
x = h(x)
x = i(x)
return x
MONAD x = 3
x = 5
x = 17
x = 4 x = -9
x = 7
x = 12
CPU #1 CPU #2
x = 4 x = -9
Shared Memory, x
![Page 64: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/64.jpg)
MONADAs you can see, the same function results in indeterminate results depending on the whims of the parallel OS-controlled POSIX threads (“pthreads”)
We expect that when we write the code (“computation logic”) for f(x), when given x = 3, f(x) will always result in -3 but because x is mutable in traditional languages, this is not the case if we try to make our program run on multiple CPUs.
![Page 65: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/65.jpg)
MONADImperative languages that we are familiar with solve this problem with
• locks (semaphores) on POSIX threads; or
• green threads (concurrent threads) and asynchronous I/O
![Page 66: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/66.jpg)
MONADHaskell has everything + more performant approaches:
• sparks (super-duper lightweight green threads)
• green threads
• semaphores
• immutable variables by default, “side effects” (mutability) achieved via monads
![Page 67: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/67.jpg)
f (x)
x1 = g(x)
x2 = h(x1)
x3 = i(x2)
return x3
f (x)
x1 = g(x)
x2 = h(x1)
x3 = i(x2)
return x3
MONAD x = 3
x1 = 5
x2 = 10
x3 = -3 x3 = -3
x1 = 5
x2 = 10
CPU #1 CPU #2
x3 = -3 x3 = -3
![Page 68: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/68.jpg)
MONADHaskell
f :: Num a => a -> a
f x = let
x1 = x + 2
x2 = x1 + 5
x3 = x2 - 13
in x3
f :: Num a => a -> a
f x = let
x = x + 2
x = x + 5
x = x - 13
in x
error :variables in haskell
are immutable values!no side effects!
![Page 69: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/69.jpg)
MONADSo, now, we know the Why?
avoid mutable state while chaining a group of functions together (or executing a sequence of logic)
So, how can a monad achieve the magic illustrated in the previous 2 slides?
![Page 70: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/70.jpg)
MONADHow?
• type container
• return
• bind
![Page 71: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/71.jpg)
MONADvar Maybe = function(value) { // container
this.value = value;
};
Maybe.prototype.ret = function() { // return
return this.value;
};
Maybe.prototype.bind = function(func) { // bind
if (this.value !== null) {
return func(this.value);
}
return this.value;
};
JavaScript
![Page 72: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/72.jpg)
MONAD// lift: takes in a function that returns a normal value and changes it in a monad
Maybe.lift = function(func) {
return function(value) {
return new Maybe(func(value));
};
};
// Usage
var addOne = function(value) {
return value + 1;
};
// we can use this with bind
var maybeAddOne = Maybe.lift(addOne);
JavaScript
![Page 73: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/73.jpg)
MONAD// lift2 use closures to get values from the two monads
// before running it through function, handling the undefined cases
Maybe.lift2 = function(func) {
return function(M1, M2) {
return new Maybe(M1.bind(function(value1){
return M2.bind(function(value2) {
return func(value1, value2);
});
}));
};
};
JavaScript
![Page 74: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/74.jpg)
MONADvar add = function(a, b) {return a + b;};
var m1 = new Maybe(1);
var m2 = new Maybe(2);
var m3 = new Maybe(undefined);
var liftM2Add = Maybe.lift2(add);
liftM2Add(m1, m2).ret(); //3
liftM2Add(m3, m2).ret(); //undefined
liftM2Add(m1, m3).ret(); //undefined
JavaScript
![Page 75: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/75.jpg)
MONADa :: Maybe Integer
a = Just 1
f :: Integer -‐> Maybe Integer
f = \x -‐> Just (x + 1)
main :: IO ()
main = do
let ans = a >>= f
print ans {-‐ we expect to get Just 2 -‐}
Haskell
![Page 76: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/76.jpg)
MONAD• type container
• return
• bind
• We pass in function(s) to operate values inside it
• and get a returned value
![Page 77: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/77.jpg)
MONADThe code
• http://github.com/calvinchengx/learnhaskell
![Page 79: Functional Programming for OO Programmers (part 2)](https://reader034.fdocuments.in/reader034/viewer/2022051516/55a522301a28abb4348b47e2/html5/thumbnails/79.jpg)
CRAFTSMANSHIPMaster your craft - Procedural, OO, Functional