Functional programming
Imperative
vs
Declarative programming
U = IR
What language is functional?
Main things
- Function is a first-class and higher-order citizen
- Pure functions
- Recurtion
- Algebraic data types
- Strict versus non-strict evaluation (nice to have)
main = map (\x -> 3 * x + 1) [1, 2, 3, 4, 5]
const fn = arr => (prop, asc) => arr.slice().sort((a, b) => {
return asc * (a[prop] > b[prop] ? 1 : (a[prop] === b[prop] ? 0 : -1));
});
const sorter = fn([{a: 1}, {a: 2}, {a: 3}]);
// a lot of lines after
sorter("a", 1);
// a few more lines of code
sorter("a", -1);
Pure functions
function fn (a, b) {
console.log(a, b);
return a + b;
}
Math.random()
Date.now()
main = let a = 3
b = 1
in map (\x -> a * x + b) [1, 2, 3, 4, 5]
const fn = arr => (prop, asc) => arr.slice().sort((a, b) => {
return asc * (a[prop] > b[prop] ? 1 : (a[prop] === b[prop] ? 0 : -1));
});
function () {
let hash = {
// some data
};
return function (item) {
return hash[item.id];
}
}
function () {
let hash = {
// some data
};
return function (item) {
if (!hash[item.id]) {
hash[item.id] = item;
}
return hash[item.id];
}
}
Recurtion
There are no loops
function factorial(x) {
if (x <= 0) {
return 1;
} else {
return x * factorial(x-1); // (A)
}
}
factorial(100000);
Tail call optimizations
function id(x) {
return x; // (A)
}
function f(a) {
let b = a + 1;
return id(b); // (B)
}
console.log(f(2)); // (C)
C
B
A
B
C
Tail call
function id(x) {
return x; // (A)
}
function f(a) {
let b = a + 1;
return id(b); // (B)
}
console.log(f(2)); // (C)
C
B
A
What can be optimized?
const a = x => x ? f() : g();
const a = () => f() || g();
const a = () => f() && g();
const a = () => (f() , g());
function foo() {
bar();
}
function foo() {
bar();
return undefined;
}
function factorial(x) {
if (x <= 0) {
return 1;
} else {
return x * factorial(x-1); // (A)
}
}
function factorial(n) {
return facRec(n, 1);
}
function facRec(x, acc) {
if (x <= 1) {
return acc;
} else {
return facRec(x-1, x*acc); // (A)
}
}
Why?
function a() { return b() }
function b() { return c() }
function c() { console.trace() ..// would not include b()!
Algebraic data types
Types are also functions
data Bool = False | True
data List a = Nil
| Cons a (List a)
data Type :: * -> * where
Char :: Type Char
Int :: Type Int
List :: Type a -> Type [a]
sum :: Type a -> a -> Int
sum Char _ = 0
sum Int n = n
sum (List a) xs = foldr (+) 0 (map (sum a) xs)
f :: Int -> Int
f 0 = 1
f 1 = 5
f 2 = 2
f _ = -1
map _ [] = []
map f (x:xs) = f x : map f xs
hello :: Pet -> String
hello x =
case x of
Cat -> "meeow"
Dog -> "woof"
Fish -> "bubble"
Strict versus non-strict evaluation
print length([2+1, 3*2, 1/0, 5-4])
How we can do?
Immutable data structures
Category theory
Functor
data Maybe a = Nothing | Just a
Функтор — это класс типов.
> fmap (+3) (Just 2)
Just 5
instance Functor Maybe where
fmap func (Just val) = Just (func val)
fmap func Nothing = Nothing
post = Post.find_by_id(1)
if post
return post.title
else
return nil
end
getPostTitle <$> (findPost 1)
Example of Functor?
what if?
fmap (+3) (+1)
> import Control.Applicative
> let foo = fmap (+3) (+2)
> foo 10
15
Applicatives
Just (+3) <*> Just 2 == Just 5
> (+) <$> (Just 5)
Just (+5)
> Just (+5) <$> (Just 4)
> (+) <$> (Just 5)
Just (+5)
> Just (+5) <*> (Just 3)
Just 8
> (*) <$> Just 5 <*> Just 3
Just 15
Monads
half x = if even x
then Just (x `div` 2)
else Nothing
Monad — ещё один класс типов
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
instance Monad Maybe where
Nothing >>= func = Nothing
Just val >>= func = func val
> Just 20 >>= half >>= half >>= half
Nothing
IO монада
getLine >>= readFile >>= putStrLn
Questions?
Functional programming
By Vladimir
Functional programming
- 139