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

Demystifying Functional Programming

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 

Tamizhvendan S

May 29, 2018
Tweet

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