Anupam
December 21, 2017
220

# Introduction to Functional Programming for absolute beginners

A 2 hour presentation given at S&P Gurgaon on 21st Dec 2017

## Anupam

December 21, 2017

## Transcript

2. ### FUNCTIONAL PROGRAMMING WHO AM I ▸ Programming professionally for over

12 years ▸ Organise FPNCR Meetup group ▸ The usual suspects - Javascript, Java, Ruby, Python, C ▸ Discovered Functional Programming around 2004 ▸ Lisp -> (OCaml, Erlang) -> Clean -> … -> Haskell ▸ Elm, Purescript, countless others 2 * Please join
3. ### FUNCTIONAL PROGRAMMING FP IN NCR ▸ The Delhi/NCR Haskell and

other Functional Programming Languages Meetup Group ▸ https://www.meetup.com/DelhiNCR-Haskell-And-Functional-Programming- Languages-Group ▸ FPNCR Github Organisation - common projects, propose talks, etc. ▸ https://github.com/fpncr ▸ FPNCR Mailing List ▸ https://groups.google.com/forum/#!forum/fpncr ▸ FPNCR Channel on Slack ▸ https://functionalprogramming.slack.com - #FPNCR 3
4. ### FUNCTIONAL PROGRAMMING WHAT IS FUNCTIONAL PROGRAMMING ▸ Functions ▸ Modularity

▸ Composition ▸ Abstraction 4 SOFTWARE DESIGN
5. ### FUNCTIONAL PROGRAMMING SIMPLICITY ▸ Single Unit of abstraction - Functions

▸ Functions are Values ▸ All Values can be passed to Functions 5
6. ### FUNCTIONAL PROGRAMMING SIMPLE FUNCTIONS 1 fib :: Integer -> Integer

2 fib 0 = 1 3 fib 1 = 1 4 fib n = fib (n-1) + fib (n-2) 6
7. ### FUNCTIONAL PROGRAMMING CASE EXPRESSIONS 1 fib :: Integer -> Integer

2 fib n = case n of 3 0 -> 1 4 1 -> 1 5 n -> fib (n-1) + fib (n-2) 7
8. ### FUNCTIONAL PROGRAMMING ANONYMOUS FUNCTIONS 1 fib :: Integer -> Integer

2 fib = \n -> case n of 3 0 -> 1 4 1 -> 1 5 n -> fib (n-1) + fib (n-2) 8
9. ### FUNCTIONAL PROGRAMMING GUARDS 1 fib :: Integer -> Integer 2

fib n 3 | n < 2 = 1 4 | otherwise = fib (n-1) + fib (n-2) 9
10. ### FUNCTIONAL PROGRAMMING THINGS THAT MAKE HASKELL UNIQUE ▸ Strongly Typed

unlike Clojure ▸ Pure unlike OCaml, Scala ▸ Lazy unlike Purescript, Elm 10
11. ### FUNCTIONAL PROGRAMMING STRONG STATIC TYPING ▸ Checked at compile time

▸ Not the same as Types in, say, Java ▸ Slight Hyperbole - “If it compiles it works” ▸ Reality - “Refactor without fear” ▸ Let the computer help you help yourself 11
12. ### FUNCTIONAL PROGRAMMING STRONG STATIC TYPING ▸ Primitive Types ▸ Algebraic

Data Types ▸ Recursive Types ▸ Function Types ▸ Pattern Matching ▸ Totality 12
13. ### FUNCTIONAL PROGRAMMING PRIMITIVE TYPES ▸ Void ▸ () = ()

▸ Bool = True | False ▸ Char = ‘a’ | ‘b’ | … ▸ Integer = 0 | 1 | … ▸ String = [Char] 13
14. ### FUNCTIONAL PROGRAMMING ALGEBRAIC DATA TYPES 1 data Shape 2 =

Square 3 | Circle 4 | Triangle 5 6 data User 7 = Root 8 | Login String 14
15. ### FUNCTIONAL PROGRAMMING DATA TYPES WITH PARAMS 1 data Maybe a

2 = Nothing 3 | Just a 4 5 data Either a b 6 = Left a 7 | Right b 15
16. ### FUNCTIONAL PROGRAMMING RECURSIVE DATA TYPES 1 data List a 2

= Empty 3 | Cons a (List a) 4 5 data Tree a 6 = Leaf a 7 | Branch (Tree a) (Tree a) 8 16
17. ### FUNCTIONAL PROGRAMMING TYPED FIRST CLASS FUNCTIONS 1 data Ordering 2

= LT | GT | EQ 3 5 type Cmp a = a -> a -> Ordering 6 7 sort :: Cmp a -> [a] -> [a] 17
18. ### FUNCTIONAL PROGRAMMING COMPOSITION VS INHERITANCE ▸ Don’t inherit, compose ▸

Vehicle > Car > RacingCar ▸ data RacingCar = RacingCar VehicleData CarData RacingCarData 18
19. ### FUNCTIONAL PROGRAMMING DEFINING FUNCTIONS WITH PATTERN MATCHING 1 data List

a 2 = Empty 3 | Cons a (List a) 4 5 cdr :: List a -> List a 6 cdr Empty = ?? 7 cdr (Cons _ rest) = rest 8 9 car :: List a -> a 10 car Empty = ?? 11 car (Cons a _) = a 12 19
20. ### FUNCTIONAL PROGRAMMING PATTERN MATCHING (CONTD…) 1 data List a 2

= Empty 3 | Cons a (List a) 4 5 cdr :: List a -> List a 6 cdr Empty = Empty 7 cdr (Cons _ rest) = rest 8 9 car :: List a -> Maybe a 10 car Empty = Nothing 11 car (Cons a _) = Just a 12 13 data Maybe a = Nothing | Just a 14 20
21. ### FUNCTIONAL PROGRAMMING LIST CONCATENATION 1 data List a 2 =

Empty 3 | Cons a (List a) 4 5 concat :: List a -> List a -> List a 6 concat Empty b = b 7 concat a Empty = a 8 concat (Cons x xs) b@(Cons _ _) 9 = Cons x (concat xs b) 10 21
22. ### FUNCTIONAL PROGRAMMING PYTHON 1 class Cell: 2 def __init__( self,

data, next = None ): 3 self.data = data 4 self.next = next 5 6 def concat(A, B): 7 current = A 8 while current.next != None: 9 current = current.next 10 current.next = B 11 return A 22
23. ### HASKELL 101 PYTHON def concat(A, B): current = A while

current.next != None: current = current.next current.next = B return A 23 concat Empty b = b concat a Empty = a concat (Cons x xs) b = Cons x (concat xs b) HASKELL FIGHT!
24. ### HASKELL 101 PYTHON def concat(A, B): current = A while

current.next != None: current = current.next current.next = B return A 24 concat Empty b = b concat a Empty = a concat (Cons x xs) b = Cons x (concat xs b) HASKELL TEST assertEq(concat('','bar'), 'bar') assertEq(concat('foo',''), 'foo') assertEq(concat(‘foo’,'bar'), 'foobar')
25. ### HASKELL 101 PYTHON def concat(A, B): current = A while

current.next != None: current = current.next current.next = B return A 25 concat Empty b = b concat a Empty = a concat (Cons x xs) b = Cons x (concat xs b) HASKELL
26. ### THERE ARE TWO WAYS OF CONSTRUCTING A SOFTWARE DESIGN: ONE

WAY IS TO MAKE IT SO COMPLICATED THAT THERE ARE NO OBVIOUS DEFICIENCIES, AND THE OTHER WAY IS TO MAKE IT SO SIMPLE THAT THERE ARE OBVIOUSLY NO DEFICIENCIES. - C.A.R. Hoare, 1980 ACM Turing Award Lecture HASKELL 101 26
27. ### FUNCTIONAL PROGRAMMING BUT WHAT ABOUT... ▸ Monads? ▸ “It’s just

Monoids in the category of endofunctors. What is the problem?” ▸ Category Theory ▸ Blah Blah 27
28. ### FUNCTIONAL PROGRAMMING You can ignore all the abstract math stuff

and yet be highly productive with  Functional Programming 28
29. ### FUNCTIONAL PROGRAMMING Haskell lets me write code that I am

not smart enough to write. 29

31. ### HASKELL 101 SUM NUMBERS FROM 1 TO 10 1 total

= 0, count = 1 2 while count <= 10: 3 total = total + count 4 count = count + 1 31 1 total = sum [1..10]
32. ### FUNCTIONAL PROGRAMMING ABSTRACTION ▸ The shared vocabulary that allows us

to write concise, high level, programs 32
33. ### HASKELL 101 SHARED VOCABULARY COMPARED 1 total = 0, count

= 1 2 while count <= 10: 3 total = total + count 4 count = count + 1 33 1 total = sum [1..10]
34. ### FUNCTIONAL PROGRAMMING SUM ELEMENTS OF A LIST 1 sum ::

[Int] -> Int 2 sum [] = 0 3 sum (x:xs) = x + sum xs 4 34
35. ### FUNCTIONAL PROGRAMMING MULTIPLY ELEMENTS OF A LIST 1 prod ::

[Int] -> Int 2 prod [] = 0 3 prod (x:xs) = x * sum xs 4 35
36. ### FUNCTIONAL PROGRAMMING ABSTRACTION 1 fold :: (a -> Int ->

a) -> a -> [Int] -> a 2 fold _ a [] = a 3 fold f a (x:xs) = fold f (f a x) xs 4 36
37. ### FUNCTIONAL PROGRAMMING FOLD OVER ELEMENTS OF A LIST 1 sum

= fold (+) 0 2 prod = fold (*) 1 3 37
38. ### FUNCTIONAL PROGRAMMING IS ANY/ALL BOOLEAN TRUE 1 any = fold

(||) False 2 all = fold (&&) True 3 38
39. ### FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS > 3 1 anyLarge =

fold (\p e -> p || e > 3) False 2 allLarge = fold (\p e -> p && e > 3) True 3 39
40. ### FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS DIGITS 1 anyDigit = fold

(\p e -> p || isDigit e) False 2 allDigit = fold (\p e -> p && isDigit e) True 3 40
41. ### FUNCTIONAL PROGRAMMING MORE ABSTRACTION! 1 foldMap :: (a -> Int

-> a) -> (Int -> Int) -> a -> [Int] -> a 2 foldMap _ _ a [] = a 3 foldMap f m a (x:xs) = foldMap f m (f a (m x)) xs 4 41
42. ### FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS > 3 1 anyLarge =

foldMap (||) (> 3) False 2 allLarge = foldMap (&&) (> 3) True 3 42
43. ### FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS DIGITS 1 anyDigit = foldMap

(||) isDigit False 2 allDigit = foldMap (&&) isDigit True 3 43

45. ### FUNCTIONAL PROGRAMMING WHY ▸ Easy to understand what's going on

▸ Cleanly separated “logic” ((&&), isdigit, etc.) ▸ Common machinery (foldMap) can be easily reused ▸ Easy to test functions in isolation 45
46. ### FUNCTIONAL PROGRAMMING BUT… ▸ foldMap has 3 arguments that are

not easy to remember ▸ It's harder to generalise this pattern. Should we keep on adding arguments to fold/foldMap? 46
47. ### FUNCTIONAL PROGRAMMING WE CAN ABSTRACT FURTHER 1 compose2 :: (a

-> b -> d) -> (x -> b) -> a -> x -> d 2 compose2 f m a x = f a (m x) 3 foldMap f m a (x:xs) = foldMap f m (f a (m x)) xs 4 = foldMap f m (compose2 f m a x) xs foldMap f m a (x:xs) = fold (compose2 f m) a x xs 47
48. ### FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS > 3 1 anyLarge =

fold (compose2 (||) (> 3)) False 2 allLarge = fold (compose2 (&&) (> 3)) True 3 48
49. ### FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS DIGITS 1 anyDigit = fold

(compose2 (||) isDigit) False 2 allDigit = fold (compose2 (&&) isDigit) True 3 49
50. ### FUNCTIONAL PROGRAMMING MUCH BETTER ▸ We removed an extra function

(foldMap) which was actually not needed ▸ Our existing machinery (fold) turned out to be powerful enough to support our logic ▸ We reduced code complexity by introducing another “orthogonal” and “generic” shared vocabulary (compose2) 50
51. ### FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS DIGITS 1 anyDigit = fold

(compose2 (||) isDigit) False 2 allDigit = fold (compose2 (&&) isDigit) True 3 51
52. ### PERFECTION IS ATTAINED NOT WHEN THERE IS NOTHING MORE TO

ADD, BUT WHEN THERE IS NOTHING MORE TO REMOVE. - Antoine de Saint Exupéry HASKELL 101 52
53. ### FUNCTIONAL PROGRAMMING GO DEEPER 1 (.) :: (b -> c)

-> (a -> b) -> a -> c 2 (.) f g a = f (g a) 3 4 flip :: (a -> b -> c) -> b -> a -> c 5 flip f b a = f a b 6 53
54. ### FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS DIGITS 1 anyDigit = fold

(flip ((||) . isDigit)) False 2 allDigit = fold (flip ((&&) . isDigit)) True 3 54
55. ### FUNCTIONAL PROGRAMMING FUNCTIONS ARE DATA PIPELINES (flip ((||) . isDigit))

a b = ((||) . isDigit) b a = ((||) (isDigit b)) a = a || isDigit b 55
56. ### FUNCTIONAL PROGRAMMING THIS IS SPARTA HASKELL 1 module Main where

2 3 main :: IO () 4 main = do 5 putStrLn "Hello Haskell!" 6 56
57. ### FUNCTIONAL PROGRAMMING THIS IS SPARTA HASKELL 1 module Main where

2 3 main :: IO () 4 main = do 5 putStrLn "What is your name?" 6 name <- getLine 7 putStrLn ("Hello " ++ name ++ “!") 8 57
58. ### FUNCTIONAL PROGRAMMING THIS IS SPARTA HASKELL 1 module Main where

2 3 main :: IO () 4 main = do 5 name <- getName 6 putStrLn ("Hello " ++ name ++ "!") 7 8 getName :: IO String 9 getName = do 10 putStrLn "What is your name?" 11 getLine 58
59. ### FUNCTIONAL PROGRAMMING “IO” DENOTES MUTATION 1 main :: IO ()

2 main = do 3 name <- getName 4 showGreeting name 5 6 showGreeting :: String -> IO () 7 showGreeting name = putStrLn (greeting name) 8 9 getName :: IO String 10 getName = ... 11 12 greeting :: String -> String 13 greeting name = "Hello " ++ name ++ "!" 59

62. ### FUNCTIONAL PROGRAMMING WAI-ROUTES - TYPE SAFE WEB ROUTING data MyRoute

= HomeR | HelloR Text renderRoute :: MyRoute -> [Text] parseRoute :: [Text] -> MyRoute 62 Check out https://github.com/ajnsit/wai-routes
63. ### FUNCTIONAL PROGRAMMING GENERATED WEB SERVER ROUTING case getPathInfo req of

"hello" : arg : [] -> case getReqMethod req of GET -> getHello arg req POST -> postHello arg req 63
64. ### FUNCTIONAL PROGRAMMING REAL WORLD HASKELL getAlbumsR :: Handler AlbumRoute getAlbumsR

= runHandlerM \$ do Just token <- reqHeader “Authorisation” auth <- liftIO \$ post (showRoute ValidateR) token if isValid auth then status 403 >> json err else json albums 64
65. ### FUNCTIONAL PROGRAMMING CONCUR - EXTREMELY SIMPLE UI FRAMEWORK main =

liftIO (R.randomRIO (1,100)) >>= go where go n = do guessStr <- el "div" [] [ text "Try to guess: " , inputEnter [] ] case readMaybe guessStr of Nothing -> go n Just guess -> do if | guess < n -> el_ "div" [] (text \$"Go High!") <|> go n | guess > n -> el_ "div" [] (text \$"Go Low!") <|> go n | otherwise -> el_ "div" [] (text \$ "You guessed it!”) <|> (button [] (text "Play again")) 65 Check out https://github.com/ajnsit/concur

67. ### FUNCTIONAL PROGRAMMING FUNCTOR CLASS 1 class Functor f where 2

fmap :: (a -> b) -> f a -> f b 67
68. ### FUNCTIONAL PROGRAMMING FOLDABLE CLASS 1 class Foldable f where 2

foldr :: (b -> a -> b) -> b -> f a -> b 68
69. ### FUNCTIONAL PROGRAMMING LIST INSTANCES 2 instance Functor [] where 3

fmap f [] = [] 4 fmap f (x:xs) = (f x: map f xs) 5 6 instance Foldable [] where 7 foldl f b [] = b 8 foldl f b (x:xs) = foldl f (f b x) xs 69
70. ### FUNCTIONAL PROGRAMMING ANY DATA STRUCTURE CAN BE FOLDED ▸ When

Data is Non-Recursive, its the same as fmap ▸ When a data structure is recursive, each recursive part needs to be handled separately 70
71. ### FUNCTIONAL PROGRAMMING TREE 2 instance Functor Tree where 3 fmap

f (Leaf a) = Leaf (f a) 4 fmap f (Branch x y) = Branch (fmap f x) (fmap f y) 5 6 instance Foldable Tree where 7 foldl f b (Leaf a) = f b a 8 foldl f b (Branch x y) = ?? (foldl f b x) (foldl f b y) 71
72. ### FUNCTIONAL PROGRAMMING FOLD TREE 1 foldTree :: (b -> a

-> b) -> (b -> b -> b) -> b 2 -> Tree a -> b 3 foldTree f g b (Leaf a) = f b a 4 foldTree f g b (Branch x y) 5 = g (foldTree f g b x) (foldTree f g b y) 72
73. ### FUNCTIONAL PROGRAMMING ANOTHER COMMON PATTERN 1 foldTree :: (b ->

a -> b) -> (b -> b -> b) -> b 2 -> Tree a -> b 3 foldTree f g b (Leaf a) = f b a 4 foldTree f g b (Branch x y) 5 = g (foldTree f g b x) (foldTree f g b y) 73
74. ### FUNCTIONAL PROGRAMMING MONOID 1 class Monoid m where 2 (<>)

:: m -> m -> m 74
75. ### FUNCTIONAL PROGRAMMING FOLDABLE TREE REVISITED 1 foldTree :: Monoid b

=> (b -> a -> b) -> b 2 -> Tree a -> b 3 foldTree f b (Leaf a) = f b a 4 foldTree f b (Branch x y) 5 = foldTree f b x <> foldTree f b y 75

77. ### FUNCTIONAL PROGRAMMING ALGEBRAIC DATA TYPES 1 data Maybe a 2

= Nothing 3 | Just a 4 5 data Either a b 6 = Left a 7 | Right b 8 9 data Person 10 = Empty 11 | Cons a (List a) 12 13 data Tree a 14 = Leaf a 15 | Branch (Tree a) (Tree a) 16 77

79. ### FUNCTIONAL PROGRAMMING TEMPLATE HASKELL mkRoute "MyRoute" [parseRoutes| / HomeR GET

/hello/#Text HelloR GET POST |] 79