Slide 1

Slide 1 text

FUNCTIONAL PROGRAMMING FOR ABSOLUTE BEGINNERS ANUPAM JAIN

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

FUNCTIONAL PROGRAMMING WHAT IS FUNCTIONAL PROGRAMMING ▸ Functions ▸ Modularity ▸ Composition ▸ Abstraction 4 SOFTWARE DESIGN

Slide 5

Slide 5 text

FUNCTIONAL PROGRAMMING SIMPLICITY ▸ Single Unit of abstraction - Functions ▸ Functions are Values ▸ All Values can be passed to Functions 5

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

FUNCTIONAL PROGRAMMING GUARDS 1 fib :: Integer -> Integer 2 fib n 3 | n < 2 = 1 4 | otherwise = fib (n-1) + fib (n-2) 9

Slide 10

Slide 10 text

FUNCTIONAL PROGRAMMING THINGS THAT MAKE HASKELL UNIQUE ▸ Strongly Typed unlike Clojure ▸ Pure unlike OCaml, Scala ▸ Lazy unlike Purescript, Elm 10

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

FUNCTIONAL PROGRAMMING STRONG STATIC TYPING ▸ Primitive Types ▸ Algebraic Data Types ▸ Recursive Types ▸ Function Types ▸ Pattern Matching ▸ Totality 12

Slide 13

Slide 13 text

FUNCTIONAL PROGRAMMING PRIMITIVE TYPES ▸ Void ▸ () = () ▸ Bool = True | False ▸ Char = ‘a’ | ‘b’ | … ▸ Integer = 0 | 1 | … ▸ String = [Char] 13

Slide 14

Slide 14 text

FUNCTIONAL PROGRAMMING ALGEBRAIC DATA TYPES 1 data Shape 2 = Square 3 | Circle 4 | Triangle 5 6 data User 7 = Root 8 | Login String 14

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

FUNCTIONAL PROGRAMMING COMPOSITION VS INHERITANCE ▸ Don’t inherit, compose ▸ Vehicle > Car > RacingCar ▸ data RacingCar = RacingCar VehicleData CarData RacingCarData 18

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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!

Slide 24

Slide 24 text

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')

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

FUNCTIONAL PROGRAMMING BUT WHAT ABOUT... ▸ Monads? ▸ “It’s just Monoids in the category of endofunctors. What is the problem?” ▸ Category Theory ▸ Blah Blah 27

Slide 28

Slide 28 text

FUNCTIONAL PROGRAMMING You can ignore all the abstract math stuff and yet be highly productive with
 Functional Programming 28

Slide 29

Slide 29 text

FUNCTIONAL PROGRAMMING Haskell lets me write code that I am not smart enough to write. 29

Slide 30

Slide 30 text

ABSTRACTION

Slide 31

Slide 31 text

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]

Slide 32

Slide 32 text

FUNCTIONAL PROGRAMMING ABSTRACTION ▸ The shared vocabulary that allows us to write concise, high level, programs 32

Slide 33

Slide 33 text

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]

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

FUNCTIONAL PROGRAMMING FOLD OVER ELEMENTS OF A LIST 1 sum = fold (+) 0 2 prod = fold (*) 1 3 37

Slide 38

Slide 38 text

FUNCTIONAL PROGRAMMING IS ANY/ALL BOOLEAN TRUE 1 any = fold (||) False 2 all = fold (&&) True 3 38

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS > 3 1 anyLarge = foldMap (||) (> 3) False 2 allLarge = foldMap (&&) (> 3) True 3 42

Slide 43

Slide 43 text

FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS DIGITS 1 anyDigit = foldMap (||) isDigit False 2 allDigit = foldMap (&&) isDigit True 3 43

Slide 44

Slide 44 text

FUNCTIONAL PROGRAMMING WHY? 44

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS > 3 1 anyLarge = fold (compose2 (||) (> 3)) False 2 allLarge = fold (compose2 (&&) (> 3)) True 3 48

Slide 49

Slide 49 text

FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS DIGITS 1 anyDigit = fold (compose2 (||) isDigit) False 2 allDigit = fold (compose2 (&&) isDigit) True 3 49

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS DIGITS 1 anyDigit = fold (compose2 (||) isDigit) False 2 allDigit = fold (compose2 (&&) isDigit) True 3 51

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

FUNCTIONAL PROGRAMMING ARE ANY/ALL ELEMENTS DIGITS 1 anyDigit = fold (flip ((||) . isDigit)) False 2 allDigit = fold (flip ((&&) . isDigit)) True 3 54

Slide 55

Slide 55 text

FUNCTIONAL PROGRAMMING FUNCTIONS ARE DATA PIPELINES (flip ((||) . isDigit)) a b = ((||) . isDigit) b a = ((||) (isDigit b)) a = a || isDigit b 55

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

REAL WORLD

Slide 61

Slide 61 text

SERVER

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

EXTRA TIME

Slide 67

Slide 67 text

FUNCTIONAL PROGRAMMING FUNCTOR CLASS 1 class Functor f where 2 fmap :: (a -> b) -> f a -> f b 67

Slide 68

Slide 68 text

FUNCTIONAL PROGRAMMING FOLDABLE CLASS 1 class Foldable f where 2 foldr :: (b -> a -> b) -> b -> f a -> b 68

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

FUNCTIONAL PROGRAMMING MONOID 1 class Monoid m where 2 (<>) :: m -> m -> m 74

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

FIN Questions?

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

SUPERFICIAL OVERVIEW

Slide 79

Slide 79 text

FUNCTIONAL PROGRAMMING TEMPLATE HASKELL mkRoute "MyRoute" [parseRoutes| / HomeR GET /hello/#Text HelloR GET POST |] 79