Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Demystifying Functional Programming

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers. →

Demystifying Functional Programming

Because of some perceived complexities and the mathematical background in functional programming, the beginners get bogged down while learning and putting it into practice. As a matter of fact, few people give up after some initial attempts. But it is not as much harder as we think. It is just different!

Together, let's experience a different perspective of functional programming and get started in a better way 

Avatar for Tamizhvendan S

Tamizhvendan S

May 29, 2018

More Decks by Tamizhvendan S

Other Decks in Programming

Transcript

  1. Demystifying Functional Programming tamizhvendan tamizhvendan Lead Consultant www.ajira.tech Tamizhvendan S

    Passionate, Pragmatic and Polyglot Programmer https://www.demystifyfp.com λ
  2. int numbers[3] = {2,3,4}, squaredNumbers[3]; for (int i = 0;

    i < 3; i!++) { squaredNumbers[i] = numbers[i] * numbers[i]; }
  3. “A language that doesn’t affect the way you think about

    programming, is not worth knowing.” - Alan Perlis
  4. “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
  5. “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
  6. “Design is to take things apart in a such a

    way that they can be put back together” - Rich Hickey
  7. <img src="cat.jpg" alt="cat" /> type Element = { Name :

    string Attributes : Attribute list }
  8. <p> This is a paragraph </p> type Element = {

    Name : string Attributes : Attribute list Content : Content } and Content = PlainText of string
  9. <textarea rows="4"> </textarea> type Element = { Name : string

    Attributes : Attribute list Content : Content option } and Content = PlainText of string
  10. <ul> <li>Coffee</li> <li>Tea</li> </ul> type Element = { Name :

    string Attributes : Attribute list Content : Content option } and Content = | PlainText of string | ChildElements of Element list
  11. 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
  12. Element !-> string let beveragesList = let content = childElements

    [ element "li" [] (plainText "Tea") element "li" [] (plainText "Coffee")] element "ul" [("class", "ulist")] content
  13. Map

  14. What we have What we want List<string> !-> string string

    !-> List<string> !-> string String.concat
  15. string !-> List<string> !-> string String.concat <img src="cat.jpg" alt="cat" />

    String.concat " " string !-> List<string> !-> string
  16. Expect the output of every program to become the input

    of another, as yet unknown, program” - Unix Philosophy
  17. Function Composition Using Piping // List<Attribute>  string let attrsToHtmlStr

    attrs = List.map attrToHtmlStr attrs  String.concat " "
  18. // List<Attribute>  string let attrsToHtmlStr attrs = attrs 

    List.map attrToHtmlStr  String.concat " " partial application
  19. let attrs = [ {Name = "src"; Value = "cat.jpg"}

    {Name = "alt"; Value = "cat"} ]
  20. Map (A !-> B) !-> List<A> !-> List<B> Partial Application

    string !-> List<string> !-> string Function Composition A !-> B B !-> C A !-> C
  21. Pattern Matching // Content  string let contentToHtmlStr content =

    match content with | PlainText x  x | ChildElements xs  xs  List.map elementToHtmlStr  String.concat ""
  22. map

  23. map

  24. What we have What we want Element !-> string Option<Content>

    !-> string List<Attribute> !-> string
  25. 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
  26. let beveragesList = let content = childElements [ element "li"

    [] (plainText "Tea") element "li" [] (plainText "Coffee")] element "ul" [("class", "ulist")] content
  27. // int  Result<Element, string> let getElementById id = if

    id = 1 then Ok beveragesList else Error "unable to fetch"
  28. map

  29. map

  30. (A !-> B) !-> List<A> !-> List<B> map (A !->

    B) !-> Result<A,C> !-> Result<B,C> (A !-> B) !-> F<A> !-> F<B> (A !-> B) !-> Option<A> !-> Option<B>
  31. 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} )
  32. 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
  33. What we have What we want Element !-> Element !->

    Element List<Attribute>  List<Attribute>  List<Attribute> Content  Content  Content
  34. What we have What we want Content  Content 

    Content Option<Content> !-> Option<Content> !-> Option<Content>
  35. 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}
  36. What we have What we want Element  Element 

    Element Result<Element,string> !-> Result<Element,string> !-> Result<Element,string>
  37. let getAndMergeElements e1Id e2Id = let e1R = getElementById e1Id

    let e2R = getElementById e2Id Result.lift2 mergeElement e1R e2R
  38. A !-> B !-> C Option<A> !-> Option<B> !-> Option<C>

    lift2 Result<A,E> !-> Result<B,E> !-> Result<C,E> (A !-> B !-> C) !-> AP<A> !-> AP<B> !-> AP<C> List<A> !-> List<B> !-> List<C>
  39. map (A !-> B) !-> F<A> !-> F<B> lift2 (A

    !-> B !-> C) !-> AP<A> !-> AP<B> !-> AP<C>
  40. lift3 (A !-> B !-> C !-> D) !-> AP<A>

    !-> AP<B> !-> AP<C> !-> AP<D> liftN
  41. // int  Result<Configuration, string> let getConfigurationById id = if

    id = 1 then Ok {Id = 1; ElementId = 1} else Error "unable to fetch"
  42. What we have What we want int !-> Result<Configuration, string>

    int !-> Result<Element, string> int !-> Result<Element, string> configuration id element id configuration id
  43. bind (A !-> M<B>) !-> M<A> !-> M<B> (A !->

    Result<B, C>) !-> Result<A,C> !-> Result<B, C> (A !-> List<B>) !-> List<A> !-> List<B> (A !-> Option<B>) !-> Option<A> !-> Option<B>
  44. map (A !-> B) !-> F<A> !-> F<B> lift2 (A

    !-> B !-> C) !-> AP<A> !-> AP<B> !-> AP<C> bind (A !-> M<B>) !-> M<A> !-> M<B>
  45. Prompt<string> let namePrompt : Prompt<string> = stringPrompt "What's Your name?”

    > namePrompt();; What’s your name? Tamizhvendan val it : Result<string, PromptError> = Ok “Tamizhvendan”
  46. Prompt<int> let agePrompt : Prompt<int> = intPrompt "What's Your age?”

    > agePrompt();; What’s your age? 29 val it : Result<string, PromptError> = Ok 29 > agePrompt();; What’s your age? foobar val it : Result<string, PromptError> = Error ParserError
  47. 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<string, PromptError> = Ok “Hey Tamizhvendan, you are 29 years old!” lift2
  48. 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<string, PromptError> = Ok “Hey Tamizhvendan, you are 39 years old!” map
  49. apply AP<(A !-> B)> !-> AP<A> !-> AP<B> append MO<A>

    !-> MO<A> !-> MO<A> fold (A !-> B !-> A) !-> A !-> FO<B> !-> A
  50. FP Demystified λ Algebraic Data Types λ Separate Pure &

    Impure Functions λ Function Signature Matters! λ map, liftN, bind, etc., λ Have Fun!! https://www.demystifyfp.com