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

Adopting Functional Programming

Adopting Functional Programming

Apple’s new language Swift supports functional programming while being tightly integrated with Objective-C and Cocoa. This has sent the developer community on an adventure to explore how ideas from functional programming might help writing great apps for iOS and OS X. In this talk, I will concentrate on two of these ideas: types and immutable data structures. How do they benefit development, and how do they affect code architecture?

This talk was presented at Sydney CocoaHeads who have kindly produced a video of the talk: http://sydneycocoaheads.com/2014/08/27/swift-adopting-functional-programming-by-manuel-chakravarty/

2296a6bdc7779fe4017a23d268c8a79d?s=128

Manuel Chakravarty
PRO

August 21, 2014
Tweet

Transcript

  1. Manuel M T Chakravarty University of New South Wales Adopting

    Functional Programming mchakravarty TacticalGrace justtesting.org 1 45 minute time slot [15+min Intro & What is FP?; 15-min Love Types; 15-min Minimise State]
  2. 2 My FP background: * Co-founder of the Programming Languages

    & Systems research group at UNSW * Internationally renowned research group: Haskell standardisation & type system; parallel programming * Program Chair of ICFP 2014
  3. GPUs multicore CPUs 3 * Current work focuses on array

    programming for high-performance architectures, such as GPUs and multicores.
  4. BIGPIXEL 4 My Cocoa background: * BigPixel — pixel art

    and sprite editor for iPad * New mixed-language Mac app » Let’s talk about Swift…
  5. BIGPIXEL 4 My Cocoa background: * BigPixel — pixel art

    and sprite editor for iPad * New mixed-language Mac app » Let’s talk about Swift…
  6. Swift Objective-C without the C 5 * Craig Federighi (apparently):

    Objective-C without the C * But Chris Lattner corrected that on the DevForums: ObjC + FP <https:// devforums.apple.com/message/1025388#1025388>
  7. Swift Objective-C with functional programming 5 * Craig Federighi (apparently):

    Objective-C without the C * But Chris Lattner corrected that on the DevForums: ObjC + FP <https:// devforums.apple.com/message/1025388#1025388>
  8. “What is functional programming?” 6 » What is functional programming?

    [Audience opinions…]
  9. Types systems Types inference Generics Pattern matching REPL Higher-order functions

    Immutable structures Garbage collection Closures Purity Well-defined semantics Meta programming Equational reasoning List comprehensions Lambda calculus Monads etc. 7 * Collection of technologies * Usually draw inspiration from mathematics * Aimed at improving program composition * Modern Objective-C already adopts some of these technologies * Swift adopts many more
  10. Types systems Types inference Generics Pattern matching REPL Higher-order functions

    Closures Garbage collection Immutable structures Purity Well-defined semantics Meta programming Equational reasoning List comprehensions Lambda calculus Monads etc. 7 * Collection of technologies * Usually draw inspiration from mathematics * Aimed at improving program composition * Modern Objective-C already adopts some of these technologies * Swift adopts many more
  11. Types inference Types systems Higher-order functions Generics REPL Pattern matching

    Closures Garbage collection Immutable structures Purity Well-defined semantics Meta programming Equational reasoning List comprehensions Lambda calculus Monads etc. 7 * Collection of technologies * Usually draw inspiration from mathematics * Aimed at improving program composition * Modern Objective-C already adopts some of these technologies * Swift adopts many more
  12. ? 8 * It’s great to have a new language

    with lots of new, exciting features, but… * …it also leads to many questions. * When should you start looking into it? How to use new features? * What is the right way to use it? Where to use it? Where to find the time? * Consider this: How much Swift in WWDC 2014 videos? What about 2015?
  13. ? When? How? What? Where? 8 * It’s great to

    have a new language with lots of new, exciting features, but… * …it also leads to many questions. * When should you start looking into it? How to use new features? * What is the right way to use it? Where to use it? Where to find the time? * Consider this: How much Swift in WWDC 2014 videos? What about 2015?
  14. ? When? How? What? Where? WWDC 2015 8 * It’s

    great to have a new language with lots of new, exciting features, but… * …it also leads to many questions. * When should you start looking into it? How to use new features? * What is the right way to use it? Where to use it? Where to find the time? * Consider this: How much Swift in WWDC 2014 videos? What about 2015?
  15. “Should I learn functional programming?” 9 * The one overarching

    question…and its follow up… » Let’s consult history…
  16. “Should I learn functional programming?” “Can you afford not to?”

    9 * The one overarching question…and its follow up… » Let’s consult history…
  17. A little history 10 * First came generics (Martin Odersky,

    Phil Wadler et al.) — based on Standard ML’s parametric polymorphism [Phil was one of the main people on the original Haskell Committee] * Then the rest (Martin Odersky et al.)
  18. A little history Generics 10 * First came generics (Martin

    Odersky, Phil Wadler et al.) — based on Standard ML’s parametric polymorphism [Phil was one of the main people on the original Haskell Committee] * Then the rest (Martin Odersky et al.)
  19. A little history Closures Types inference Types systems Higher-order functions

    Generics Pattern matching List comprehensions Monads etc. 10 * First came generics (Martin Odersky, Phil Wadler et al.) — based on Standard ML’s parametric polymorphism [Phil was one of the main people on the original Haskell Committee] * Then the rest (Martin Odersky et al.)
  20. A little history Closures Types inference Types systems Higher-order functions

    Generics Pattern matching List comprehensions Monads etc. 11 * Then the rest (Martin Odersky et al.) * Similar situation as with Swift
  21. A little history 11 * Then the rest (Martin Odersky

    et al.) * Similar situation as with Swift
  22. 12 * Java is still big, but… * …often the

    interesting projects are in Scala * See companies like Twitter, Atlassian, CBA * Big difference: Swift is from same company as the language it succeeds * So, I reckon Swift will replace Objective-C much more quickly
  23. 12 * Java is still big, but… * …often the

    interesting projects are in Scala * See companies like Twitter, Atlassian, CBA * Big difference: Swift is from same company as the language it succeeds * So, I reckon Swift will replace Objective-C much more quickly
  24. scalaz Argonaut ScalaCheck shapeless Monocle scodec 13 * How Scala

    is used: fancy Java or adopting FP * The questions is, do you want to be part of the conversation? » It seems like a good idea to look more closely at FP
  25. “What is the practical benefit of functional programming?” 14 *

    There are many success stories (Ericsson, Twitter, Facebook, WhatsApp, and so on) * But we want something more concrete…
  26. Less testing! 15 * They tell you, more tests are

    better. That’s actually nonsense. Less tests are better.
  27. 16 * Common coder wisdom: everything else being equal, it

    is better to have less code.
  28. Example code courtesy NSHipster (CC BY-NC 4.0): http://nshipster.com/xctestcase/ 17 *

    Tests are code (you have to write them, you have to debug them, you have to maintain them, you have to run them)
  29. “What if you could gain the same confidence in correctness

    with less or simpler tests?” 18 * You would spend less time writing, maintaining, and running tests.
  30. Possible states of your application 19 * Error states =

    if you reach such a state, your application will misbehave * Tested states = error states shown to be unreachable & valid states shown to be reachable * Functional programming aims to statically reduce the possible states » How do we get rid of unnecessary states?
  31. Possible states of your application Error states 19 * Error

    states = if you reach such a state, your application will misbehave * Tested states = error states shown to be unreachable & valid states shown to be reachable * Functional programming aims to statically reduce the possible states » How do we get rid of unnecessary states?
  32. Possible states of your application Error states Tested states 19

    * Error states = if you reach such a state, your application will misbehave * Tested states = error states shown to be unreachable & valid states shown to be reachable * Functional programming aims to statically reduce the possible states » How do we get rid of unnecessary states?
  33. Possible states of your application Error states Tested states 19

    * Error states = if you reach such a state, your application will misbehave * Tested states = error states shown to be unreachable & valid states shown to be reachable * Functional programming aims to statically reduce the possible states » How do we get rid of unnecessary states?
  34. Possible states of your application Error states Tested states eliminate

    bugs 19 * Error states = if you reach such a state, your application will misbehave * Tested states = error states shown to be unreachable & valid states shown to be reachable * Functional programming aims to statically reduce the possible states » How do we get rid of unnecessary states?
  35. Possible states of your application Error states Tested states eliminate

    bugs eliminate tests 19 * Error states = if you reach such a state, your application will misbehave * Tested states = error states shown to be unreachable & valid states shown to be reachable * Functional programming aims to statically reduce the possible states » How do we get rid of unnecessary states?
  36. Design Rule 1 Love types 20 * We will look

    at two FP design rules in this talk. * Let’s start with types!
  37. “A type signature is worth a thousand tests.” 21 »

    Let’s look at a simple example…
  38. @interface MyInventory : NSObject @property NSDictionary *inventory; - (NSInteger)lookup:(NSString *)item;

    @end @implementation MyInventory - (instancetype)init { self = [super init]; if (self) _inventory = @{@"iPad Air": @10, @"MacBook Pro": @3, @"iPhone 5S": @7}; return self; } - (NSInteger)lookup:(NSString *)item { return [(NSNumber *)self.inventory[item]) integerValue]; } @end 22 * If we accidentally add a non-numeric value, [-lookup:] will crash.
  39. @interface MyInventory : NSObject @property NSDictionary *inventory; - (NSInteger)lookup:(NSString *)item;

    @end @implementation MyInventory - (instancetype)init { self = [super init]; if (self) _inventory = @{@"iPad Air": @10, @"MacBook Pro": @3, @"iPhone 5S": @7}; return self; } - (NSInteger)lookup:(NSString *)item { return [(NSNumber *)self.inventory[item]) integerValue]; } @end @[@7]}; 22 * If we accidentally add a non-numeric value, [-lookup:] will crash.
  40. class MyInventory { let inventory: [String: Int] = ["iPad Air":

    10, ! ! ! ! ! ! ! ! ! ! ! ! ! "MacBook Pro": 3, ! ! ! ! ! ! ! ! ! ! ! ! ! "iPhone 5S": 7] func lookup(item: String) -> Int? { return inventory[item] } } 23 * How awesome is Swift?!? * If we try to add a non-numeric value, we get a type error. (Same if we tried it via a function.) * How to test the ObjC version? One test is not sufficient. * This is a simple example? What if dict not static? What if value type varies per dict?
  41. class MyInventory { let inventory: [String: Int] = ["iPad Air":

    10, ! ! ! ! ! ! ! ! ! ! ! ! ! "MacBook Pro": 3, ! ! ! ! ! ! ! ! ! ! ! ! ! "iPhone 5S": 7] func lookup(item: String) -> Int? { return inventory[item] } } [7]] 23 * How awesome is Swift?!? * If we try to add a non-numeric value, we get a type error. (Same if we tried it via a function.) * How to test the ObjC version? One test is not sufficient. * This is a simple example? What if dict not static? What if value type varies per dict?
  42. class MyInventory { let inventory: [String: Int] = ["iPad Air":

    10, ! ! ! ! ! ! ! ! ! ! ! ! ! "MacBook Pro": 3, ! ! ! ! ! ! ! ! ! ! ! ! ! "iPhone 5S": 7] func lookup(item: String) -> Int? { return inventory[item] } } [7]] ⛔️ dictionary type 23 * How awesome is Swift?!? * If we try to add a non-numeric value, we get a type error. (Same if we tried it via a function.) * How to test the ObjC version? One test is not sufficient. * This is a simple example? What if dict not static? What if value type varies per dict?
  43. [Key: Value] == Dictionary<Key, Value> [String: Int] == Dictionary<String, Int>

    24 * This is not limited to builtin types. You can use the same power in your own definitions.
  44. struct Dictionary<Key : Hashable, Value> : CollectionType, DictionaryLiteralConvertible { …

    } [Key: Value] == Dictionary<Key, Value> [String: Int] == Dictionary<String, Int> 24 * This is not limited to builtin types. You can use the same power in your own definitions.
  45. func i<T>(x: T) -> T { return x } The

    expressiveness of types ??? 25 * Guess the function! (Assuming no type inspection nor non-termination) * Try this with tests. * ”Theorems for free!” (aka parametricity)
  46. func i<T>(x: T) -> T { return x } The

    expressiveness of types 25 * Guess the function! (Assuming no type inspection nor non-termination) * Try this with tests. * ”Theorems for free!” (aka parametricity)
  47. func i<T>(x: T) -> T { return x } func

    m<T, U>(f: (T -> U), a: [T]) -> [U] { return a.map(f) } The expressiveness of types ??? 25 * Guess the function! (Assuming no type inspection nor non-termination) * Try this with tests. * ”Theorems for free!” (aka parametricity)
  48. func i<T>(x: T) -> T { return x } func

    m<T, U>(f: (T -> U), a: [T]) -> [U] { return a.map(f) } The expressiveness of types 25 * Guess the function! (Assuming no type inspection nor non-termination) * Try this with tests. * ”Theorems for free!” (aka parametricity)
  49. func i<T>(x: T) -> T { return x } func

    m<T, U>(f: (T -> U), a: [T]) -> [U] { return a.map(f) } func r<T, U>(e: U, f: ((U, T) -> U), a: [T]) -> U { return a.reduce(e, combine: f) } The expressiveness of types ??? 25 * Guess the function! (Assuming no type inspection nor non-termination) * Try this with tests. * ”Theorems for free!” (aka parametricity)
  50. func i<T>(x: T) -> T { return x } func

    m<T, U>(f: (T -> U), a: [T]) -> [U] { return a.map(f) } func r<T, U>(e: U, f: ((U, T) -> U), a: [T]) -> U { return a.reduce(e, combine: f) } The expressiveness of types 25 * Guess the function! (Assuming no type inspection nor non-termination) * Try this with tests. * ”Theorems for free!” (aka parametricity)
  51. func i<T>(x: T) -> T { return x } func

    m<T, U>(f: (T -> U), a: [T]) -> [U] { return a.map(f) } func r<T, U>(e: U, f: ((U, T) -> U), a: [T]) -> U { return a.reduce(e, combine: f) } The expressiveness of types Try this: write a unit test giving the same guarantees 25 * Guess the function! (Assuming no type inspection nor non-termination) * Try this with tests. * ”Theorems for free!” (aka parametricity)
  52. Types let the compiler eliminate (error) states 26 * Test

    frameworks are run less frequently * Usually, because they are slow: they typically alway test everything * Not bit rot » That gets us to the second design rule…
  53. Types let the compiler eliminate (error) states Every single time

    you build ✓ 26 * Test frameworks are run less frequently * Usually, because they are slow: they typically alway test everything * Not bit rot » That gets us to the second design rule…
  54. Types let the compiler eliminate (error) states Every single time

    you build ✓ Only checks what changed ✓ 26 * Test frameworks are run less frequently * Usually, because they are slow: they typically alway test everything * Not bit rot » That gets us to the second design rule…
  55. Types let the compiler eliminate (error) states Every single time

    you build ✓ Only checks what changed ✓ ✓ Checked documentation 26 * Test frameworks are run less frequently * Usually, because they are slow: they typically alway test everything * Not bit rot » That gets us to the second design rule…
  56. Design Rule 2 Minimise (mutable) state 27 * The second

    design rule is about managing state differently.
  57. Possible states of your application 28

  58. Possible states of your application Lack of composition 28

  59. Possible states of your application Lack of composition Mutable data

    28
  60. Possible states of your application Lack of composition Interdependent data

    Duplicating data Mutable data 28
  61. WWDC 2014, Session 229 Advanced iOS Application Architecture and Patterns

    29 * This is a large topic, and it would take too long now to go into much detail. * For concrete advice and examples, see this great talk by Andy Matuschak and Colin Barrett » Applying these ideas can be tricky…
  62. WWDC 2014, Session 229 Advanced iOS Application Architecture and Patterns

    Avoid state duplication 29 * This is a large topic, and it would take too long now to go into much detail. * For concrete advice and examples, see this great talk by Andy Matuschak and Colin Barrett » Applying these ideas can be tricky…
  63. WWDC 2014, Session 229 Advanced iOS Application Architecture and Patterns

    Avoid state duplication Use immutable data 29 * This is a large topic, and it would take too long now to go into much detail. * For concrete advice and examples, see this great talk by Andy Matuschak and Colin Barrett » Applying these ideas can be tricky…
  64. M V C 30 * Applying these ideas to existing

    apps can be hard * Especially with bloated controllers
  65. M V C Kitchen sink 30 * Applying these ideas

    to existing apps can be hard * Especially with bloated controllers
  66. M V Citchen sink K 31 * View owns the

    view model * View model adapts the model to be suitable for presentation * View model can be unit tested (independent of views & view controllers) * We need AppKit & UIKit controller classes: but keep controllers small
  67. M V C V M iew odel 31 * View

    owns the view model * View model adapts the model to be suitable for presentation * View model can be unit tested (independent of views & view controllers) * We need AppKit & UIKit controller classes: but keep controllers small
  68. M V C V M iew odel ownership 31 *

    View owns the view model * View model adapts the model to be suitable for presentation * View model can be unit tested (independent of views & view controllers) * We need AppKit & UIKit controller classes: but keep controllers small
  69. M V C V M iew odel adapt model for

    presentation ownership 31 * View owns the view model * View model adapts the model to be suitable for presentation * View model can be unit tested (independent of views & view controllers) * We need AppKit & UIKit controller classes: but keep controllers small
  70. M V C V M iew odel adapt model for

    presentation suitable for unit testing ownership 31 * View owns the view model * View model adapts the model to be suitable for presentation * View model can be unit tested (independent of views & view controllers) * We need AppKit & UIKit controller classes: but keep controllers small
  71. M V C V M iew odel &C adapt model

    for presentation suitable for unit testing ownership 31 * View owns the view model * View model adapts the model to be suitable for presentation * View model can be unit tested (independent of views & view controllers) * We need AppKit & UIKit controller classes: but keep controllers small
  72. Possible states of your application 32 * Immutable models in

    Swift using structs, enums & classes with readonly properties (lets)
  73. Possible states of your application simple relationship between view state

    and the state of the view model ✓ 32 * Immutable models in Swift using structs, enums & classes with readonly properties (lets)
  74. Possible states of your application simple relationship between view state

    and the state of the view model ✓ (parts of the) model can be immutable ✓ 32 * Immutable models in Swift using structs, enums & classes with readonly properties (lets)
  75. struct Project { let name: String let image: UIImage let

    canvas: Canvas let url: NSURL // Create empty project init(name: String) // Create project for image at URL init(url: NSURL) // Create project from image for fixed URL init(image: UIImage, name: String, url: NSURL) // Rename project func rename(name: String) -> Project // Remove project backing file func remove() } 33 * No aliasing to worry about * Tests don’t depend on context (except the file system — which is global mutable state) * Cf. blog post by Alexandros Salazar: http://nomothetis.svbtle.com/immutable-swift
  76. types >< state Questions to ask How can I use

    types to eliminate tests? How can I minimise state to eliminate tests? 34 » For some more background on the universal nature of FP…
  77. “Do Extraterrestrials Use Functional Programming?” https://speakerdeck.com/mchakravarty/do-extraterrestrials-use-functional-programming 2013 35 * YOW!

    Lambda Jam 2013 keynote * Annual conference on functional programming for developers in Australia
  78. Thank you! 36

  79. "Nile blue 05" by Kuebi = Armin Kübelbeck - Own

    work. CC BY-SA 3.0 - http://commons.wikimedia.org/wiki/File:Nile_blue_05.jpg Images from http://wikimedia.org http://openclipart.org 37