Slide 1

Slide 1 text

Demystifying Functional Programming tamizhvendan tamizhvendan Lead Consultant www.ajira.tech Tamizhvendan S Passionate, Pragmatic and Polyglot Programmer https://www.demystifyfp.com λ

Slide 2

Slide 2 text

Why Functional Programming?

Slide 3

Slide 3 text

Solution Problem

Slide 4

Slide 4 text

Solution Problem

Slide 5

Slide 5 text

Vehicle Influences The Journey

Slide 6

Slide 6 text

Solution Problem

Slide 7

Slide 7 text

Language Influences The Thinking

Slide 8

Slide 8 text

int numbers[3] = {2,3,4}, squaredNumbers[3]; for (int i = 0; i < 3; i!++) { squaredNumbers[i] = numbers[i] * numbers[i]; }

Slide 9

Slide 9 text

let numbers = [1,2,3]; let squaredNumbers = numbers.map(n !=> n * n);

Slide 10

Slide 10 text

“A language that doesn’t affect the way you think about programming, is not worth knowing.” - Alan Perlis

Slide 11

Slide 11 text

Solution Problem Challenges

Slide 12

Slide 12 text

Domain Complexity Requirement Change Time To Market Reliability

Slide 13

Slide 13 text

Solution Problem Abstractions

Slide 14

Slide 14 text

Inheritance Encapsulation Polymorphism

Slide 15

Slide 15 text

GoF Patterns!

Slide 16

Slide 16 text

Inheritance Encapsulation Polymorphism GoF Patterns! Better Abstractions

Slide 17

Slide 17 text

Functional Programming

Slide 18

Slide 18 text

Solution Problem Better Abstractions

Slide 19

Slide 19 text

FP Three Step Approach

Slide 20

Slide 20 text

Step-1 Model The Domain (Data)

Slide 21

Slide 21 text

“Data dominates. If you’ve chose the right data structures & organise things well, the algorithms will almost be self-evident. Data structures, not algorithms, are central to programming” - Rob Pike

Slide 22

Slide 22 text

Step-2 Define The Behaviour (Algorithm)

Slide 23

Slide 23 text

“Make each program do one thing well. To do a new job, build afresh rather than complicate the old programs by adding new “features”. Expect the output of every program to become the input of another, as yet unknown, program” - Unix Philosophy

Slide 24

Slide 24 text

Step-3 Define The System (Composition)

Slide 25

Slide 25 text

“Design is to take things apart in a such a way that they can be put back together” - Rich Hickey

Slide 26

Slide 26 text

Separation of Concerns Composition

Slide 27

Slide 27 text

Dynamic HTML Generation

Slide 28

Slide 28 text

Step-1 Model The Domain (Data)

Slide 29

Slide 29 text

type Attribute = { Name : string Value : string }

Slide 30

Slide 30 text

cat type Element = { Name : string Attributes : Attribute list }

Slide 31

Slide 31 text

This is a paragraph

type Element = { Name : string Attributes : Attribute list Content : Content } and Content = PlainText of string

Slide 32

Slide 32 text

type Element = { Name : string Attributes : Attribute list Content : Content option } and Content = PlainText of string

Slide 33

Slide 33 text

  • Coffee
  • Tea
type Element = { Name : string Attributes : Attribute list Content : Content option } and Content = | PlainText of string | ChildElements of Element list

Slide 34

Slide 34 text

Algebraic Data Types type Element = { Name : string Attributes : Attribute list Content : Content option } and Content = | PlainText of string | ChildElements of Element list Sum (or Choice) Type Product Type

Slide 35

Slide 35 text

Step-2 Define The Behaviour

Slide 36

Slide 36 text

Element !-> string let beveragesList = let content = childElements [ element "li" [] (plainText "Tea") element "li" [] (plainText "Coffee")] element "ul" [("class", "ulist")] content

Slide 37

Slide 37 text

Step-3 Divide & Conquer (Compose)

Slide 38

Slide 38 text

Attribute !-> string

Slide 39

Slide 39 text

// Attribute  string let attrToHtmlStr attr = sprintf @"%s=""%s""" attr.Name attr.Value

Slide 40

Slide 40 text

List !-> string

Slide 41

Slide 41 text

List !-> string List !-> List List !-> string

Slide 42

Slide 42 text

What we have What we want List !-> List Attribute !-> string

Slide 43

Slide 43 text

Map

Slide 44

Slide 44 text

// List  List let attrsToHtmlStr attrs = List.map attrToHtmlStr attrs (A !-> B) !-> List !-> List List.map

Slide 45

Slide 45 text

What we have What we want List !-> string string !-> List !-> string String.concat

Slide 46

Slide 46 text

Partial Application partially providing the argument(s) string !-> List !-> string

Slide 47

Slide 47 text

string !-> List !-> string String.concat cat String.concat " " string !-> List !-> string

Slide 48

Slide 48 text

What we have List !-> List List !-> string What we want List !-> string

Slide 49

Slide 49 text

Expect the output of every program to become the input of another, as yet unknown, program” - Unix Philosophy

Slide 50

Slide 50 text

A !-> B B !-> C A !-> C Function Composition

Slide 51

Slide 51 text

Function Composition // List  string let attrsToHtmlStr = List.map attrToHtmlStr  String.concat " "

Slide 52

Slide 52 text

Function Composition Using Piping // List  string let attrsToHtmlStr attrs = List.map attrToHtmlStr attrs  String.concat " "

Slide 53

Slide 53 text

// List  string let attrsToHtmlStr attrs = attrs  List.map attrToHtmlStr  String.concat " " partial application

Slide 54

Slide 54 text

let attrs = [ {Name = "src"; Value = "cat.jpg"} {Name = "alt"; Value = "cat"} ]

Slide 56

Slide 56 text

Option !-> string

Slide 57

Slide 57 text

Content !-> string

Slide 58

Slide 58 text

Pattern Matching // Content  string let contentToHtmlStr content = match content with | PlainText x  x | ChildElements xs  xs  List.map elementToHtmlStr  String.concat ""

Slide 59

Slide 59 text

What we have What we want Option !-> string Content !-> string

Slide 60

Slide 60 text

Option !-> string Option !-> Option Option !-> string

Slide 61

Slide 61 text

What we have What we want Content !-> string Option !-> Option

Slide 62

Slide 62 text

map

Slide 63

Slide 63 text

map

Slide 64

Slide 64 text

// Option let contentOpt = element.Content  Option.map contentToHtmlStr

Slide 65

Slide 65 text

let content = defaultArg contentOpt "" Option !-> string core library function

Slide 66

Slide 66 text

What we have What we want Element !-> string Option !-> string List !-> string

Slide 67

Slide 67 text

let elementToHtmlStr element = let attrs = attrsToHtmlStr element.Attributes let contentOpt = element.Content  Option.map contentToHtmlStr let content = defaultArg contentOpt “" let tag = element.Name sprintf "<%s %s> %s %s>" tag attrs content tag

Slide 68

Slide 68 text

let beveragesList = let content = childElements [ element "li" [] (plainText "Tea") element "li" [] (plainText "Coffee")] element "ul" [("class", "ulist")] content

Slide 69

Slide 69 text

Error Handling

Slide 70

Slide 70 text

Result (Either) Type int !-> Result

Slide 71

Slide 71 text

// int  Result let getElementById id = if id = 1 then Ok beveragesList else Error "unable to fetch"

Slide 72

Slide 72 text

Transform Element to Html String after fetching

Slide 73

Slide 73 text

What we have What we want Result !-> Result Element !-> string

Slide 74

Slide 74 text

map

Slide 75

Slide 75 text

map

Slide 76

Slide 76 text

// int  Result let getHtmlStrById id = getElementById id  Result.map elementToHtmlStr

Slide 77

Slide 77 text

map Preserves The Structure

Slide 78

Slide 78 text

map Transforms The Value

Slide 80

Slide 80 text

No content

Slide 81

Slide 81 text

Merging Elements! Element !-> Element !-> Element

Slide 82

Slide 82 text

List  List  List Merging Attributes

Slide 83

Slide 83 text

let mergeAttrs attrs1 attrs2 = attrs1 @ attrs2  List.groupBy (fun (a : Attribute)  a.Name)  List.map (fun (name, attrs)  let value = attrs  List.map (fun a  a.Value)  String.concat " " {Name = name; Value = value} )

Slide 84

Slide 84 text

Content  Content  Content Merging Content

Slide 85

Slide 85 text

let mergeContent content1 content2 = match content1, content2 with | PlainText x, PlainText y  sprintf "%s\n%s" x y  PlainText | ChildElements xs, ChildElements ys  ChildElements (xs @ ys) | _  content1

Slide 86

Slide 86 text

What we have What we want Element !-> Element !-> Element List  List  List Content  Content  Content

Slide 87

Slide 87 text

type Element = { Name : string Attributes : Attribute list Content : Content option }

Slide 88

Slide 88 text

What we have What we want Content  Content  Content Option !-> Option !-> Option

Slide 89

Slide 89 text

aka map2 lift2

Slide 90

Slide 90 text

let mergeElement e1 e2 = let attrs = mergeAttrs e1.Attributes e2.Attributes let content = Option.lift2 mergeContent e1.Content e2.Content { Name = e1.Name Attributes = attrs Content = content}

Slide 91

Slide 91 text

Merge Elements after fetching Result !-> Result !-> Result

Slide 92

Slide 92 text

What we have What we want Element  Element  Element Result !-> Result !-> Result

Slide 93

Slide 93 text

lift2

Slide 94

Slide 94 text

let getAndMergeElements e1Id e2Id = let e1R = getElementById e1Id let e2R = getElementById e2Id Result.lift2 mergeElement e1R e2R

Slide 95

Slide 95 text

lift2

Slide 97

Slide 97 text

Slide 98

Slide 98 text

lift3 (A !-> B !-> C !-> D) !-> AP !-> AP !-> AP !-> AP liftN

Slide 99

Slide 99 text

No content

Slide 100

Slide 100 text

Each Configuration Has Own Element Id type Configuration = { Id : int ElementId : int }

Slide 101

Slide 101 text

Fetch Configuration And Then Fetch It’s Element

Slide 102

Slide 102 text

Fetch Configuration int !-> Result

Slide 103

Slide 103 text

// int  Result let getConfigurationById id = if id = 1 then Ok {Id = 1; ElementId = 1} else Error "unable to fetch"

Slide 104

Slide 104 text

What we have What we want int !-> Result int !-> Result int !-> Result configuration id element id configuration id

Slide 105

Slide 105 text

bind aka flatMap

Slide 106

Slide 106 text

let getElementByConfigId cId = getConfigurationById cId  Result.bind (fun c  getElementById c.ElementId)

Slide 107

Slide 107 text

bind aka flatMap

Slide 110

Slide 110 text

You can create your structure! FooBar map lift2 bind

Slide 111

Slide 111 text

Prompt let namePrompt : Prompt = stringPrompt "What's Your name?” > namePrompt();; What’s your name? Tamizhvendan val it : Result = Ok “Tamizhvendan”

Slide 112

Slide 112 text

Prompt let agePrompt : Prompt = intPrompt "What's Your age?” > agePrompt();; What’s your age? 29 val it : Result = Ok 29 > agePrompt();; What’s your age? foobar val it : Result = Error ParserError

Slide 113

Slide 113 text

let greeting name age = sprintf "Hey %s, you are %d years old!” name age let greetingWizard = lift2 greeting namePrompt agePrompt > greetingWizard();; What’s your name? Tamizhvendan What’s your age? 29 val it : Result = Ok “Hey Tamizhvendan, you are 29 years old!” lift2

Slide 114

Slide 114 text

let addAgeBy10Years age = age + 10 let prankWizard = agePrompt |> map addAgeBy10Years |> lift2 greeting namePrompt > prankWizard();; What’s your name? Tamizhvendan What’s your age? 29 val it : Result = Ok “Hey Tamizhvendan, you are 39 years old!” map

Slide 115

Slide 115 text

Slide 116

Slide 116 text

traverse (A !-> AP) !-> T !-> AP> sequence T> !-> AP>

Slide 117

Slide 117 text

By The Way! M AP F Functor Applicative Monad * There are some laws!

Slide 118

Slide 118 text

FP Demystified λ Algebraic Data Types λ Separate Pure & Impure Functions λ Function Signature Matters! λ map, liftN, bind, etc., λ Have Fun!! https://www.demystifyfp.com