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

Swift Functional Programming

Secret Lab
February 02, 2016

Swift Functional Programming

Overview of the basics of Functional Programming using the Swift programming language. Presented at the Functional Programming Miniconf at Linux.conf.au 2016, in Geelong.

Secret Lab

February 02, 2016
Tweet

More Decks by Secret Lab

Other Decks in Programming

Transcript

  1. Swift Functional Programming
    @parisba

    View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. Agenda
    • What is Swift
    • Why bother?
    • Installing Swift
    • Playgrounds/REPL
    • Functional Programming
    Fundamentals
    • Swift Functional
    Programming

    View Slide

  6. This is mostly a “how
    Swift does it” talk

    View Slide

  7. A quick overview.
    Not all-inclusive.

    View Slide

  8. Swift?!
    • Similar to Rust, Perl 6, and a bunch of other
    languages…
    • Another trendy, hip, cool, modern programming
    language…
    • Actually pretty good…

    View Slide

  9. Why does Swift matter?

    View Slide

  10. Swift is open source.
    swift.org

    View Slide

  11. Swift is easy to teach.

    View Slide

  12. iOS.

    View Slide

  13. http://blog.appannie.com/app-annie-2015-retrospective/
    Annual App Downloads, 2013 - 2015

    View Slide

  14. http://blog.appannie.com/app-annie-2015-retrospective/
    Annual App Revenue, 2013 - 2015

    View Slide

  15. View Slide

  16. let = ["","",""]
    for in {
    print()
    }

    View Slide

  17. Swift is not really a
    functional language

    View Slide

  18. Nothing like a pure
    functional language.

    View Slide

  19. Ideals of functional
    programming are important

    View Slide

  20. Installing Swift

    View Slide

  21. Available on Linux and OS X
    (OS X installation: just download Xcode)

    View Slide

  22. Binaries available for Ubuntu

    View Slide

  23. $ sudo apt-get install clang libicu-dev
    Download a binary from https://swift.org/download/#linux; extract it
    $ tar xzf swift--.tar.gz
    $ export PATH=/path/to/usr/bin:"${PATH}"
    This creates a usr/ directory; add it to your path:
    Swift is now installed!
    Download the pre-requisites:

    View Slide

  24. Useful Swifty Things

    View Slide

  25. Playgrounds

    View Slide

  26. $ swift
    Welcome to Apple Swift version 2.1.1 (swiftlang-700.1.101.15
    clang-700.1.81). Type :help for assistance.
    1> let text = "Don t worry if you are not computer"
    text: String = "Don t worry if you are not computer"
    2> text.uppercaseString
    $R0: String = "DON T WORRY IF YOU ARE NOT COMPUTER"
    3>

    View Slide

  27. What does functional
    programming mean?

    View Slide

  28. Functions

    View Slide

  29. First-class functions

    View Slide

  30. Higher-order functions

    View Slide

  31. Pure functions

    View Slide

  32. Pure functions have no
    side effects.

    View Slide

  33. No I/O, no changing
    outside state.

    View Slide

  34. Why does functional
    programming matter?

    View Slide

  35. © GDC CC-BY 2.0

    View Slide

  36. –John Carmack
    “No matter what language you
    work in, programming in a functional
    style provides benefits. You should
    do it whenever it is convenient, and
    you should think hard about the
    decision when it isn't convenient.”

    View Slide

  37. yeah ok but WHY

    View Slide

  38. “Pure functions have a
    lot of nice properties.”

    View Slide

  39. • Thread safety
    • Reusability
    • Testability
    • Understandability
    • Maintainability

    View Slide

  40. Important Language Support

    View Slide

  41. A really nice type system.

    View Slide

  42. First-class functions.
    See also: lambda calculus, Haskell, OCaml, Scala, and so on.

    View Slide

  43. func add(num1: Int, _ num2 : Int) -> Int {
    return num1 + num2
    }

    View Slide

  44. func add(num1: Int, _ num2 : Int) -> Int {
    return num1 + num2
    }
    var addNumbers : (Int,Int) -> Int

    View Slide

  45. func add(num1: Int, _ num2 : Int) -> Int {
    return num1 + num2
    }
    var addNumbers : (Int,Int) -> Int
    addNumbers = add

    View Slide

  46. func add(num1: Int, _ num2 : Int) -> Int {
    return num1 + num2
    }
    var addNumbers : (Int,Int) -> Int
    addNumbers = add
    addNumbers(1,2)

    View Slide

  47. Closures

    View Slide

  48. Inline first-class functions

    View Slide

  49. var add = { (num1 : Int, num2 : Int) -> Int in
    return num1 + num2
    }

    View Slide

  50. Swift will infer as much
    type info as it can

    View Slide

  51. var add = { (num1 : Int, num2 : Int) -> Int in
    return num1 + num2
    }

    View Slide

  52. var add = { (num1 : Int, num2 : Int) -> Int in
    return num1 + num2
    }

    View Slide

  53. var add = { (num1 : Int, num2 : Int) -> Int in
    return num1 + num2
    }

    View Slide

  54. var add : (Int,Int) -> Int
    add = { $0 + $1 }

    View Slide

  55. var add : (Int,Int) -> Int
    add = (+)

    View Slide

  56. Value capturing

    View Slide

  57. typealias Adder = (Int) -> Int

    View Slide

  58. typealias Adder = (Int) -> Int
    func makeAdder(number: Int) -> Adder {
    return { $0 + number }
    }

    View Slide

  59. typealias Adder = (Int) -> Int
    func makeAdder(number: Int) -> Adder {
    return { $0 + number }
    }
    let addTwo = makeAdder(2)

    View Slide

  60. typealias Adder = (Int) -> Int
    func makeAdder(number: Int) -> Adder {
    return { $0 + number }
    }
    let addTwo = makeAdder(2)
    addTwo(5) // 7

    View Slide

  61. First-class functions means
    we get higher-order functions!

    View Slide

  62. typealias TwoIntegerFunction = (Int,Int) -> Int

    View Slide

  63. typealias TwoIntegerFunction = (Int,Int) -> Int
    func applyOperationToNumbers(num1 : Int, _ num2 : Int,
    operation: TwoIntegerFunction) -> Int {
    return operation(num1, num2)
    }

    View Slide

  64. typealias TwoIntegerFunction = (Int,Int) -> Int
    func applyOperationToNumbers(num1 : Int, _ num2 : Int,
    operation: TwoIntegerFunction) -> Int {
    return operation(num1, num2)
    }
    let add : TwoIntegerFunction = { $0 + $1 }

    View Slide

  65. typealias TwoIntegerFunction = (Int,Int) -> Int
    func applyOperationToNumbers(num1 : Int, _ num2 : Int,
    operation: TwoIntegerFunction) -> Int {
    return operation(num1, num2)
    }
    let add : TwoIntegerFunction = { $0 + $1 }
    applyOperationToNumbers(2, 3, operation: add)

    View Slide

  66. typealias TwoIntegerFunction = (Int,Int) -> Int
    func applyOperationToNumbers(num1 : Int, _ num2 : Int,
    operation: TwoIntegerFunction) -> Int {
    return operation(num1, num2)
    }
    let add : TwoIntegerFunction = { $0 + $1 }
    applyOperationToNumbers(2, 3, operation: add)
    applyOperationToNumbers(2, 3, operation: +)

    View Slide

  67. Optionals

    View Slide

  68. In Swift, variables are
    never allowed to be nil,
    unless they’re Optionals.

    View Slide

  69. var text = "As you might know, I am a full time Internet"
    text.uppercaseString
    // "AS YOU MIGHT KNOW, I AM A FULL TIME INTERNET"

    View Slide

  70. let textFromDisk = loadTextFromDisk()
    textFromDisk.uppercaseString // Error!!

    View Slide

  71. Very similar to Haskell’s Maybe

    View Slide

  72. let textFromDisk = loadTextFromDisk()
    textFromDisk?.uppercaseString
    // "EVERYTHING HAPPENS SO MUCH"

    View Slide

  73. Some Contrived Examples
    using Swift

    View Slide

  74. func incrementArray(theArray: [Int]) -> [Int] {
    var result: [Int] = []
    for item in theArray {
    result.append(item+1)
    }
    return result
    }

    View Slide

  75. func doubleArray(theArray: [Int]) -> [Int] {
    var result: [Int] = []
    for item in theArray {
    result.append(item*2)
    }
    return result
    }

    View Slide

  76. typealias TransformFunction = Int -> Int
    func manipulateArray(theArray: [Int],
    transform: TransformFunction) -> [Int] {
    var result: [Int] = []
    for item in theArray {
    result.append(transform(item))
    }
    return result
    }

    View Slide

  77. func doubleArray(xs: [Int]) -> [Int] {
    return manipulateArray(xs, transform:{ $0*2 })
    }

    View Slide

  78. Limitations…

    View Slide

  79. [ ]
    , , ,
    Int Int Int Int
    [ ]
    , , ,
    Int Int Int Int

    View Slide

  80. [ ]
    , , ,
    Int Int Int Int
    [ ]
    , , ,
    ?
    Bool Bool Bool Bool

    View Slide

  81. Writing duplicate
    versions sucks

    View Slide

  82. Generics!

    View Slide

  83. func manipulateArray(theArray: [Int],
    transform: TransformFunction) -> [Int] {
    var result: [Int] = []
    for item in theArray {
    result.append(transform(item))
    }
    return result
    }

    View Slide

  84. func map(xs: [Int], transform: Int->T) -> [T] {
    var result: [T] = []
    for x in xs {
    result.append(transform(x))
    }
    return result
    }

    View Slide

  85. func map(xs: [Int], transform: Int->T) -> [T] {
    var result: [T] = []
    for x in xs {
    result.append(transform(x))
    }
    return result
    }

    View Slide

  86. But we can take it further…

    View Slide

  87. func map(xs: [Element],
    transform: Element->T) -> [T] {
    var result: [T] = []
    for x in xs {
    result.append(transform(x))
    }
    return result
    }

    View Slide

  88. let doubledArray = map([1,2,3,4], transform: { $0 * 2} )

    View Slide

  89. extension Array {
    func map(transform: (Element) -> T) -> [T] {
    var result: [T] = []
    for x in self {
    result.append(transform(x))
    }
    return result
    }
    }

    View Slide

  90. [1,2,3,4].map({ $0 * 2 })

    View Slide

  91. Map actually comes with Swift
    Hopefully you were expecting me to say that…
    … the point is, there’s no secrets to Map!

    View Slide

  92. Composing functions

    View Slide

  93. 10 11
    +1
    ×2

    View Slide

  94. 5
    10 11
    +1
    ×2

    View Slide

  95. 5
    10
    11
    +1
    ×2

    View Slide

  96. 5
    10
    11
    +1
    ×2

    View Slide

  97. 5 10
    11
    +1
    ×2

    View Slide

  98. ×2
    +1

    View Slide

  99. 11
    ×2
    +1

    View Slide

  100. 5
    11
    ×2
    +1

    View Slide

  101. 5
    11
    ×2
    +1

    View Slide

  102. // Compose a function from two functions
    func compose(funcA: T->T, _ funcB: T->T) -> T->T {
    // Return a new function that calls them both
    return { funcB(funcA($0)) }
    }

    View Slide

  103. // Compose a function from two functions
    func compose(funcA: T->T, _ funcB: T->T) -> T->T {
    // Return a new function that calls them both
    return { funcB(funcA($0)) }
    }
    // Two dumb lil functions
    let double = { $0 * 2 }
    let addOne = { $0 + 1 }

    View Slide

  104. // Compose a function from two functions
    func compose(funcA: T->T, _ funcB: T->T) -> T->T {
    // Return a new function that calls them both
    return { funcB(funcA($0)) }
    }
    // Two dumb lil functions
    let double = { $0 * 2 }
    let addOne = { $0 + 1 }
    // Compose 'em!
    let doubleAndAddOne = compose(double, addOne)

    View Slide

  105. // Compose a function from two functions
    func compose(funcA: T->T, _ funcB: T->T) -> T->T {
    // Return a new function that calls them both
    return { funcB(funcA($0)) }
    }
    // Two dumb lil functions
    let double = { $0 * 2 }
    let addOne = { $0 + 1 }
    // Compose 'em!
    let doubleAndAddOne = compose(double, addOne)
    doubleAndAddOne(5)

    View Slide

  106. Limitations!

    View Slide

  107. func compose(funcA: T->T, _ funcB: T->T) -> T->T
    These have to be the same type, for no good reason!

    View Slide

  108. Is Even? Flip Boolean
    Bool
    Int Bool
    Bool

    View Slide

  109. No
    Is Even?
    Flip Boolean

    View Slide

  110. 4
    No
    Is Even?
    Flip Boolean

    View Slide

  111. 4
    No
    Is Even?
    Flip Boolean

    View Slide

  112. func compose(funcA: T->T, _ funcB: T->T) -> T->T {
    return { funcB(funcA($0)) }
    }

    View Slide

  113. func compose(funcA: T->U, _ funcB: U->V) -> T->V {
    return { funcB(funcA($0)) }
    }

    View Slide

  114. func compose(funcA: T->U, _ funcB: U->V) -> T->V {
    return { funcB(funcA($0)) }
    }
    let isEven = { $0 % 2 == 0 } // Int -> Bool
    let flipBool = { !$0 } // Bool -> Bool
    let isNotEven = compose(isEven, flipBool) // Int -> Bool
    isNotEven(4) // false

    View Slide

  115. Third-party Stuff

    View Slide

  116. Swiftz
    https://github.com/typelift/swiftz

    View Slide

  117. Better types and tools
    for FP

    View Slide

  118. import struct Swiftz.List
    // Cycles a finite list of numbers into an infinite list.
    let finite : List = [1, 2, 3, 4, 5]
    let infiniteCycle = finite.cycle()
    // Lists also support the standard map, filter, and reduce operators.
    let l : List = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    let twoToEleven = l.map(+1) // [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    let even = l.filter((==0) • (%2)) // [2, 4, 6, 8, 10]
    let sum = l.reduce(curry(+), initial: 0) // 55
    // Plus a few more.
    let partialSums = l.scanl(curry(+), initial: 0)
    // [0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
    let firstHalf = l.take(5) // [1, 2, 3, 4, 5]
    let lastHalf = l.drop(5) // [6, 7, 8, 9, 10]

    View Slide

  119. Promissum
    https://github.com/tomlokhorst/Promissum

    View Slide

  120. Dollar.swift
    dollarswift.org

    View Slide

  121. Result
    https://github.com/antitypical/Result

    View Slide

  122. Learning more
    • Learn You a Haskell for Great Good!
    • Pearls of Functional Algorithm Design
    • Programming in Haskell (Hutton)
    • Apple’s Swift Book(s)
    • IBM Swift Resources: https://developer.ibm.com/swift/

    View Slide

  123. Thank you
    @parisba / http://www.secretlab.com.au

    View Slide