Share
Embed
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 PRO
August 21, 2014
Transcript
79 slides
-
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 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 -
GPUs multicore CPUs 3 * Current work focuses on array
programming for high-performance architectures, such as GPUs and multicores. -
BIGPIXEL 4 My Cocoa background: * BigPixel — pixel art
and sprite editor for iPad * New mixed-language Mac app » Let’s talk about Swift… -
BIGPIXEL 4 My Cocoa background: * BigPixel — pixel art
and sprite editor for iPad * New mixed-language Mac app » Let’s talk about Swift… -
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> -
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> -
“What is functional programming?” 6 » What is functional programming?
[Audience opinions…] -
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 -
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 -
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 -
? 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? -
? 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? -
? 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? -
“Should I learn functional programming?” 9 * The one overarching
question…and its follow up… » Let’s consult history… -
“Should I learn functional programming?” “Can you afford not to?”
9 * The one overarching question…and its follow up… » Let’s consult history… -
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.) -
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.) -
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.) -
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 -
A little history 11 * Then the rest (Martin Odersky
et al.) * Similar situation as with Swift -
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 -
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 -
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 -
“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… -
Less testing! 15 * They tell you, more tests are
better. That’s actually nonsense. Less tests are better. -
16 * Common coder wisdom: everything else being equal, it
is better to have less code. -
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) -
“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. -
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? -
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? -
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? -
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? -
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? -
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? -
Design Rule 1 Love types 20 * We will look
at two FP design rules in this talk. * Let’s start with types! -
“A type signature is worth a thousand tests.” 21 »
Let’s look at a simple example… -
@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. -
@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. -
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? -
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? -
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? -
[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. -
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. -
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) -
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) -
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) -
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) -
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) -
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) -
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) -
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… -
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… -
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… -
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… -
Design Rule 2 Minimise (mutable) state 27 * The second
design rule is about managing state differently. -
Possible states of your application Lack of composition Interdependent data
Duplicating data Mutable data 28 -
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… -
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… -
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… -
M V C 30 * Applying these ideas to existing
apps can be hard * Especially with bloated controllers -
M V C Kitchen sink 30 * Applying these ideas
to existing apps can be hard * Especially with bloated controllers -
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 -
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 -
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 -
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 -
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 -
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 -
Possible states of your application 32 * Immutable models in
Swift using structs, enums & classes with readonly properties (lets) -
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) -
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) -
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 -
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… -
“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 -
"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