Do the FP Shake

Thinking of recursive data structures

What is functional programming (fp)

  • Method of writing programs
  • Emphasizes immutability of data
  • Enforces the idea of function as data

What fp is not

  • fp is not a language

What fp is

  • Immutability - values are not assigned and hence not changed
  • Functional purity - pure function should not have side effects, for a given set of inputs the output is always the same
  • Referential transparency - a function can be replaced with its contents wherever it is called
In [1]:
data Maggi = Cheese | Onions | Capsicum | Garlic | Noodles | Masala Maggi Maggi deriving (Eq, Show)

empty :: Maggi
empty = Noodles

append :: Maggi -> Maggi -> Maggi
append a b = Masala a b

empty `append` Cheese `append` Onions
Eta reduce
Found:
append a b = Masala a b
Why Not:
append = Masala
Masala (Masala Noodles Cheese) Onions
In [4]:
append :: Maggi -> Maggi -> Maggi
append = Masala

append Garlic (append Onions (append Cheese empty))
Masala Garlic (Masala Onions (Masala Cheese Noodles))
In [8]:
append Garlic $ append Onions $ append Cheese empty
Layer Olives (Layer Onions (Layer Cheese Pizzabread))
In [9]:
-- Creating a list
data List a = Cons a (List a) | Blank deriving (Eq, Show)

empty :: List a
empty = Blank

append :: a -> List a -> List a
append = Cons

1 `append` (2 `append` Blank)
Cons 1 (Cons 2 Blank)
In [15]:
-- Creating a tree
data Tree a = Branch (Tree a) (Tree a) | Leaf a deriving (Eq, Show)

empty :: a -> Tree a
empty = Leaf

append :: (Ord a) => Tree a -> Tree a -> Tree a
append (Leaf newval) (Leaf val) = Branch (Leaf newval) (Leaf val)
append (Leaf newval) (Branch left right) = Branch (Leaf newval) (Branch left right)
append (Branch a b) (Leaf c) = Branch (Branch a b) (Leaf c)
append a b = Branch a b

append (append (Leaf 1) (Leaf 2)) (Branch (Leaf 2) (Leaf 3))
Branch (Branch (Leaf 1) (Leaf 2)) (Branch (Leaf 2) (Leaf 3))
In [37]:
-- Creating a binary search tree
data Tree a = Branch a (Tree a) (Tree a) | Leaf deriving (Eq, Show)

emptyTree :: Tree a
emptyTree = Leaf

sapling :: a -> Tree a
sapling val = Branch val Leaf Leaf

growTree :: (Ord a) => a -> Tree a -> Tree a
growTree newval (Branch val left right)
    | newval >= val = Branch val left (growTree newval right)
    | newval  < val = Branch val (growTree newval left) right
growTree newval Leaf = sapling newval
    
growTree 10 $ growTree 3 $ sapling 4
Branch 4 (Branch 3 Leaf Leaf) (Branch 10 Leaf Leaf)

Function is data

  • The function decides what goes in and what comes out
  • There are no variables involved data is only transformed from function to function

Understanding how to understand by understanding the dollar

:info $

  • function defintion
  • module where it was defined
  • priority
In [1]:
# Feed me a burger
def giveme_food(count):  # a pure function
    print(f"{count} burgers")
    
giveme_food(2)
2 burgers
In [3]:
# Feed me
# the function can fail due to changes made outside the context of the function, for e.g. deleting the file
def giveme_food(count):  # impure function
    with open("food.txt") as f:
        print(f"{count} {f.readline()}")

giveme_food(4)
4 pizza

In [4]:
# When I said food I meant burger
def pure_func(impure_func):  # emulating a pure function
    cache = {}
    
    def wrapped(arg):
        if arg in cache:
            return cache[arg]
        else:
            cache[arg] = impure_func(arg)
            return cache[arg]
        
    return wrapped

giveme_food_i_mean_burger = pure_func(giveme_food)  # pure func
giveme_food_i_mean_burger(5)
5 "Burger"

In [1]:
-- Immutability
x = 4  -- Ha I made a variable
x = 5  -- Ha I redefined it!!
-- Did you really? It's called shadowing.

x = x + 1  -- check this out
<interactive>:2:1: error:
    Multiple declarations of ‘x’
    Declared at: <interactive>:1:1
                 <interactive>:2:1
<interactive>:3:1: error:
    Multiple declarations of ‘x’
    Declared at: <interactive>:1:1
                 <interactive>:3:1
In [ ]:
weirdAddition x y = if x `mod` 2 == 0
                    then x
                    else x + y

weirdAddition 2 undefined
-- Laziness is the single most important quality of a programmer