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/

Manuel Chakravarty

August 21, 2014
Tweet

More Decks by Manuel Chakravarty

Other Decks in Programming

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. 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
  9. 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
  10. 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
  11. ? 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?
  12. ? 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?
  13. ? 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?
  14. “Should I learn functional programming?” 9 * The one overarching

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

    9 * The one overarching question…and its follow up… » Let’s consult history…
  16. 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.)
  17. 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.)
  18. 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.)
  19. 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
  20. A little history 11 * Then the rest (Martin Odersky

    et al.) * Similar situation as with Swift
  21. 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
  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. 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
  24. “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…
  25. Less testing! 15 * They tell you, more tests are

    better. That’s actually nonsense. Less tests are better.
  26. 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)
  27. “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.
  28. 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?
  29. 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?
  30. 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?
  31. 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?
  32. 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?
  33. 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?
  34. Design Rule 1 Love types 20 * We will look

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

    Let’s look at a simple example…
  36. @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.
  37. @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.
  38. 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?
  39. 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?
  40. 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?
  41. [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.
  42. 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.
  43. 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)
  44. 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)
  45. 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)
  46. 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)
  47. 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)
  48. 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)
  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 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)
  50. 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…
  51. 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…
  52. 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…
  53. 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…
  54. Design Rule 2 Minimise (mutable) state 27 * The second

    design rule is about managing state differently.
  55. 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…
  56. 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…
  57. 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…
  58. M V C 30 * Applying these ideas to existing

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

    to existing apps can be hard * Especially with bloated controllers
  60. 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
  61. 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
  62. 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
  63. 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
  64. 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
  65. 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
  66. Possible states of your application 32 * Immutable models in

    Swift using structs, enums & classes with readonly properties (lets)
  67. 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)
  68. 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)
  69. 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
  70. 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…
  71. "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