Slide 1

Slide 1 text

Manuel M T Chakravarty Applicative & UNSW Australia Functional Programming in a Stateful World mchakravarty TacticalGrace justtesting.org 1 30 minute time slot [10min The Problem; 6min for each of the three principles]

Slide 2

Slide 2 text

λ Abstract 2 * FP strives for pure, compositional code (human reasoning) — benefits have been discussed elsewhere * The Real World™ is stateful and full of interference (machine execution) » How do we resolve this tension?

Slide 3

Slide 3 text

λ Abstract Concrete 2 * FP strives for pure, compositional code (human reasoning) — benefits have been discussed elsewhere * The Real World™ is stateful and full of interference (machine execution) » How do we resolve this tension?

Slide 4

Slide 4 text

λ Abstract Concrete 2 * FP strives for pure, compositional code (human reasoning) — benefits have been discussed elsewhere * The Real World™ is stateful and full of interference (machine execution) » How do we resolve this tension?

Slide 5

Slide 5 text

λ Abstract Concrete Entangled 2 * FP strives for pure, compositional code (human reasoning) — benefits have been discussed elsewhere * The Real World™ is stateful and full of interference (machine execution) » How do we resolve this tension?

Slide 6

Slide 6 text

λ Abstract Concrete Compositional Entangled 2 * FP strives for pure, compositional code (human reasoning) — benefits have been discussed elsewhere * The Real World™ is stateful and full of interference (machine execution) » How do we resolve this tension?

Slide 7

Slide 7 text

λ Abstract Concrete Compositional Entangled 2 * FP strives for pure, compositional code (human reasoning) — benefits have been discussed elsewhere * The Real World™ is stateful and full of interference (machine execution) » How do we resolve this tension?

Slide 8

Slide 8 text

Anatomy of a Haskell Program 3 * The Haskell type systems enforces this architecture: functional core with an imperative shell. * The imperative shell performs I/O etc » Proven successful for…

Slide 9

Slide 9 text

Anatomy of a Haskell Program λ purely functional core 3 * The Haskell type systems enforces this architecture: functional core with an imperative shell. * The imperative shell performs I/O etc » Proven successful for…

Slide 10

Slide 10 text

Anatomy of a Haskell Program λ purely functional core imperative shell 3 * The Haskell type systems enforces this architecture: functional core with an imperative shell. * The imperative shell performs I/O etc » Proven successful for…

Slide 11

Slide 11 text

Anatomy of a Haskell Program λ purely functional core imperative shell encapsulated state 3 * The Haskell type systems enforces this architecture: functional core with an imperative shell. * The imperative shell performs I/O etc » Proven successful for…

Slide 12

Slide 12 text

Pipeline Applications 4 * Today, most FP applications are in server side code, or command line applications, etc * Pipeline applications: work well with functional-core & imperative-shell architecture * Does this transfer to client-side (desktop or mobile) applications emphasising user interaction? We have very little experience with that. » There are some Elm and F# applications, but the big change is now with…

Slide 13

Slide 13 text

Pipeline Applications Read request or data 4 * Today, most FP applications are in server side code, or command line applications, etc * Pipeline applications: work well with functional-core & imperative-shell architecture * Does this transfer to client-side (desktop or mobile) applications emphasising user interaction? We have very little experience with that. » There are some Elm and F# applications, but the big change is now with…

Slide 14

Slide 14 text

Pipeline Applications Read request or data Compute database 4 * Today, most FP applications are in server side code, or command line applications, etc * Pipeline applications: work well with functional-core & imperative-shell architecture * Does this transfer to client-side (desktop or mobile) applications emphasising user interaction? We have very little experience with that. » There are some Elm and F# applications, but the big change is now with…

Slide 15

Slide 15 text

Pipeline Applications Read request or data Compute Emit result database 4 * Today, most FP applications are in server side code, or command line applications, etc * Pipeline applications: work well with functional-core & imperative-shell architecture * Does this transfer to client-side (desktop or mobile) applications emphasising user interaction? We have very little experience with that. » There are some Elm and F# applications, but the big change is now with…

Slide 16

Slide 16 text

Pipeline Applications Read request or data Compute Emit result Server-side apps Command-line apps database Clojure Erlang Haskell Scala 4 * Today, most FP applications are in server side code, or command line applications, etc * Pipeline applications: work well with functional-core & imperative-shell architecture * Does this transfer to client-side (desktop or mobile) applications emphasising user interaction? We have very little experience with that. » There are some Elm and F# applications, but the big change is now with…

Slide 17

Slide 17 text

Pipeline Applications Read request or data Compute Emit result Server-side apps Command-line apps database Clojure Erlang Haskell Scala What about user-centric & mobile applications? 4 * Today, most FP applications are in server side code, or command line applications, etc * Pipeline applications: work well with functional-core & imperative-shell architecture * Does this transfer to client-side (desktop or mobile) applications emphasising user interaction? We have very little experience with that. » There are some Elm and F# applications, but the big change is now with…

Slide 18

Slide 18 text

Swift 5 * Unlike Scala & F#, designated successor to Objective-C by platform vendor (it is like MS deprecating C# in favour of F#) * Probably largest scale adoption of a major language in the history of PL so far * Swift is for writing *end-user* apps with a heavy UI/UX focus (mainly for mobile devices) » This is a totally different game — can we make pipeline applications fit?

Slide 19

Slide 19 text

Swift 5 * Unlike Scala & F#, designated successor to Objective-C by platform vendor (it is like MS deprecating C# in favour of F#) * Probably largest scale adoption of a major language in the history of PL so far * Swift is for writing *end-user* apps with a heavy UI/UX focus (mainly for mobile devices) » This is a totally different game — can we make pipeline applications fit?

Slide 20

Slide 20 text

Swift Can we extend pipeline applications? 5 * Unlike Scala & F#, designated successor to Objective-C by platform vendor (it is like MS deprecating C# in favour of F#) * Probably largest scale adoption of a major language in the history of PL so far * Swift is for writing *end-user* apps with a heavy UI/UX focus (mainly for mobile devices) » This is a totally different game — can we make pipeline applications fit?

Slide 21

Slide 21 text

6 * GUI code looks more likes this than a pipeline… » How can we use FP to its full advantage in this context?

Slide 22

Slide 22 text

GUI elements have their own derived state 6 * GUI code looks more likes this than a pipeline… » How can we use FP to its full advantage in this context?

Slide 23

Slide 23 text

GUI elements have their own derived state Must use OO-based platform libraries 6 * GUI code looks more likes this than a pipeline… » How can we use FP to its full advantage in this context?

Slide 24

Slide 24 text

Frequent asynchronous events GUI elements have their own derived state Must use OO-based platform libraries 6 * GUI code looks more likes this than a pipeline… » How can we use FP to its full advantage in this context?

Slide 25

Slide 25 text

Frequent asynchronous events Must be responsive GUI elements have their own derived state Must use OO-based platform libraries 6 * GUI code looks more likes this than a pipeline… » How can we use FP to its full advantage in this context?

Slide 26

Slide 26 text

“How can We Use Functional Programming in this context?” 7

Slide 27

Slide 27 text

A GUI-centric Mac app in Swift & Haskell 8 * Like any fearless scientist would do, I conducted a self experiment. * I wrote a Haskell development environment (Haskell for Mac), trying to use FP where I can (with the caveat that I had to learn Swift & AppKit on-the-fly) » Here is what I learnt…

Slide 28

Slide 28 text

A GUI-centric Mac app in Swift & Haskell 8 * Like any fearless scientist would do, I conducted a self experiment. * I wrote a Haskell development environment (Haskell for Mac), trying to use FP where I can (with the caveat that I had to learn Swift & AppKit on-the-fly) » Here is what I learnt…

Slide 29

Slide 29 text

Three Methods to Facilitate FP 9 * MVVM 㱺 view model 㱺 enables an immutable model * Immutable values 㱺 minimise mutable state 㱺 need a way to deal with changes * Time series 㱺 replaces mutating variables by a stream of immutable values

Slide 30

Slide 30 text

Three Methods to Facilitate FP Application architecture Isolate side effects with a view model 9 * MVVM 㱺 view model 㱺 enables an immutable model * Immutable values 㱺 minimise mutable state 㱺 need a way to deal with changes * Time series 㱺 replaces mutating variables by a stream of immutable values

Slide 31

Slide 31 text

Three Methods to Facilitate FP Application architecture Isolate side effects with a view model Immutable values Structs & enums over classes; and use let (not var) 9 * MVVM 㱺 view model 㱺 enables an immutable model * Immutable values 㱺 minimise mutable state 㱺 need a way to deal with changes * Time series 㱺 replaces mutating variables by a stream of immutable values

Slide 32

Slide 32 text

Three Methods to Facilitate FP Application architecture Isolate side effects with a view model Immutable values Structs & enums over classes; and use let (not var) Time series Streams of values over time replace mutable state 9 * MVVM 㱺 view model 㱺 enables an immutable model * Immutable values 㱺 minimise mutable state 㱺 need a way to deal with changes * Time series 㱺 replaces mutating variables by a stream of immutable values

Slide 33

Slide 33 text

Architecture Use a Separate View Model 10 » What is a view model?

Slide 34

Slide 34 text

What is a View Model? Controller View Model 11 * C owns and updates V & M; V & M send events to the C * VM adapts the M for the view/presentation; it isolates the M from the V & C * Good for portability & testing, but also for separating purely functional from state-based * Intro to MMVM in general, see objc.io, Issue #13

Slide 35

Slide 35 text

What is a View Model? View C Model View Model 11 * C owns and updates V & M; V & M send events to the C * VM adapts the M for the view/presentation; it isolates the M from the V & C * Good for portability & testing, but also for separating purely functional from state-based * Intro to MMVM in general, see objc.io, Issue #13

Slide 36

Slide 36 text

What is a View Model? View C Model View Model Immutable λ Hybrid Mutable 11 * C owns and updates V & M; V & M send events to the C * VM adapts the M for the view/presentation; it isolates the M from the V & C * Good for portability & testing, but also for separating purely functional from state-based * Intro to MMVM in general, see objc.io, Issue #13

Slide 37

Slide 37 text

Project Descriptions in HfM 12 » Let’s look at an example of how this plays out… * In some cases, the mapping is straight forward… * …in others it isn’t. * This conversion (in both directions) is the responsibility of the view model.

Slide 38

Slide 38 text

Project Descriptions in HfM Model Serialised Dat 12 » Let’s look at an example of how this plays out… * In some cases, the mapping is straight forward… * …in others it isn’t. * This conversion (in both directions) is the responsibility of the view model.

Slide 39

Slide 39 text

Project Descriptions in HfM View Model Serialised Dat 12 » Let’s look at an example of how this plays out… * In some cases, the mapping is straight forward… * …in others it isn’t. * This conversion (in both directions) is the responsibility of the view model.

Slide 40

Slide 40 text

Project Descriptions in HfM View Model Serialised Dat 12 » Let’s look at an example of how this plays out… * In some cases, the mapping is straight forward… * …in others it isn’t. * This conversion (in both directions) is the responsibility of the view model.

Slide 41

Slide 41 text

Project Descriptions in HfM View Model Serialised Dat 12 » Let’s look at an example of how this plays out… * In some cases, the mapping is straight forward… * …in others it isn’t. * This conversion (in both directions) is the responsibility of the view model.

Slide 42

Slide 42 text

13 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 43

Slide 43 text

Model Immutable 13 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 44

Slide 44 text

Model Immutable View Model 13 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 45

Slide 45 text

Model Immutable View Model C View 13 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 46

Slide 46 text

Model View Model C View 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 47

Slide 47 text

Model View Model C View data PackageDescription = PackageDescription { package :: PackageIdentifier, license :: License, licenseFiles :: [FilePath], copyright :: String, maintainer :: String, author :: String, stability :: String, testedWith :: [(CompilerFlavor,VersionRange)], homepage :: String, pkgUrl :: String, bugReports :: String, sourceRepos :: [SourceRepo], synopsis :: String, description :: String, category :: String, … 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 48

Slide 48 text

Model View Model C View data PackageDescription = PackageDescription { package :: PackageIdentifier, license :: License, licenseFiles :: [FilePath], copyright :: String, maintainer :: String, author :: String, stability :: String, testedWith :: [(CompilerFlavor,VersionRange)], homepage :: String, pkgUrl :: String, bugReports :: String, sourceRepos :: [SourceRepo], synopsis :: String, description :: String, category :: String, … 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 49

Slide 49 text

Model View Model C View data PackageDescription = PackageDescription { package :: PackageIdentifier, license :: License, licenseFiles :: [FilePath], copyright :: String, maintainer :: String, author :: String, stability :: String, testedWith :: [(CompilerFlavor,VersionRange)], homepage :: String, pkgUrl :: String, bugReports :: String, sourceRepos :: [SourceRepo], synopsis :: String, description :: String, category :: String, … struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 50

Slide 50 text

Model View Model C View data PackageDescription = PackageDescription { package :: PackageIdentifier, license :: License, licenseFiles :: [FilePath], copyright :: String, maintainer :: String, author :: String, stability :: String, testedWith :: [(CompilerFlavor,VersionRange)], homepage :: String, pkgUrl :: String, bugReports :: String, sourceRepos :: [SourceRepo], synopsis :: String, description :: String, category :: String, … struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 51

Slide 51 text

Model View Model C View data PackageDescription = PackageDescription { package :: PackageIdentifier, license :: License, licenseFiles :: [FilePath], copyright :: String, maintainer :: String, author :: String, stability :: String, testedWith :: [(CompilerFlavor,VersionRange)], homepage :: String, pkgUrl :: String, bugReports :: String, sourceRepos :: [SourceRepo], synopsis :: String, description :: String, category :: String, … struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 52

Slide 52 text

Model View Model C View data PackageDescription = PackageDescription { package :: PackageIdentifier, license :: License, licenseFiles :: [FilePath], copyright :: String, maintainer :: String, author :: String, stability :: String, testedWith :: [(CompilerFlavor,VersionRange)], homepage :: String, pkgUrl :: String, bugReports :: String, sourceRepos :: [SourceRepo], synopsis :: String, description :: String, category :: String, … struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 53

Slide 53 text

Model View Model C View data PackageDescription = PackageDescription { package :: PackageIdentifier, license :: License, licenseFiles :: [FilePath], copyright :: String, maintainer :: String, author :: String, stability :: String, testedWith :: [(CompilerFlavor,VersionRange)], homepage :: String, pkgUrl :: String, bugReports :: String, sourceRepos :: [SourceRepo], synopsis :: String, description :: String, category :: String, … struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 54

Slide 54 text

Model View Model C View data PackageDescription = PackageDescription { package :: PackageIdentifier, license :: License, licenseFiles :: [FilePath], copyright :: String, maintainer :: String, author :: String, stability :: String, testedWith :: [(CompilerFlavor,VersionRange)], homepage :: String, pkgUrl :: String, bugReports :: String, sourceRepos :: [SourceRepo], synopsis :: String, description :: String, category :: String, … struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … class ProjectItem: NSObject { let category: ProjectItemCategory var identifier: String … weak var parent: ProjectItem? var children: [ProjectItem] var fileWrapper: NSFileWrapper? … } 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 55

Slide 55 text

Model View Model C View data PackageDescription = PackageDescription { package :: PackageIdentifier, license :: License, licenseFiles :: [FilePath], copyright :: String, maintainer :: String, author :: String, stability :: String, testedWith :: [(CompilerFlavor,VersionRange)], homepage :: String, pkgUrl :: String, bugReports :: String, sourceRepos :: [SourceRepo], synopsis :: String, description :: String, category :: String, … struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … class ProjectItem: NSObject { let category: ProjectItemCategory var identifier: String … weak var parent: ProjectItem? var children: [ProjectItem] var fileWrapper: NSFileWrapper? … } 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 56

Slide 56 text

Model View Model C View data PackageDescription = PackageDescription { package :: PackageIdentifier, license :: License, licenseFiles :: [FilePath], copyright :: String, maintainer :: String, author :: String, stability :: String, testedWith :: [(CompilerFlavor,VersionRange)], homepage :: String, pkgUrl :: String, bugReports :: String, sourceRepos :: [SourceRepo], synopsis :: String, description :: String, category :: String, … struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … class ProjectItem: NSObject { let category: ProjectItemCategory var identifier: String … weak var parent: ProjectItem? var children: [ProjectItem] var fileWrapper: NSFileWrapper? … } 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 57

Slide 57 text

Model View Model C View data PackageDescription = PackageDescription { package :: PackageIdentifier, license :: License, licenseFiles :: [FilePath], copyright :: String, maintainer :: String, author :: String, stability :: String, testedWith :: [(CompilerFlavor,VersionRange)], homepage :: String, pkgUrl :: String, bugReports :: String, sourceRepos :: [SourceRepo], synopsis :: String, description :: String, category :: String, … struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … class ProjectItem: NSObject { let category: ProjectItemCategory var identifier: String … weak var parent: ProjectItem? var children: [ProjectItem] var fileWrapper: NSFileWrapper? … } class HeaderEditorController: NSViewController { @IBOutlet weak var nameTextField: NSTextField! … @IBOutlet var fullDescriptionTextView: NSTextView! … let packageItem: ProjectItem … } 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 58

Slide 58 text

Model View Model C View data PackageDescription = PackageDescription { package :: PackageIdentifier, license :: License, licenseFiles :: [FilePath], copyright :: String, maintainer :: String, author :: String, stability :: String, testedWith :: [(CompilerFlavor,VersionRange)], homepage :: String, pkgUrl :: String, bugReports :: String, sourceRepos :: [SourceRepo], synopsis :: String, description :: String, category :: String, … struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … class ProjectItem: NSObject { let category: ProjectItemCategory var identifier: String … weak var parent: ProjectItem? var children: [ProjectItem] var fileWrapper: NSFileWrapper? … } class HeaderEditorController: NSViewController { @IBOutlet weak var nameTextField: NSTextField! … @IBOutlet var fullDescriptionTextView: NSTextView! … let packageItem: ProjectItem … } 14 * Model: immutable in-memory representation (Haskell & Swift provide strong guarantees) * View Model: partially mutable representation (Swift provides fine-grained choice of mutability — let versus var) * View: Mostly mutable view & controller object graph (instances of Apple’s Cocoa classes or subclasses)

Slide 59

Slide 59 text

Immutable Values Minimise Mutable State 15 » A core reason to for using a view model is to facilitate an immutable model.

Slide 60

Slide 60 text

Immutable by Default 16 * At first approximation, mutability makes everything more difficult: reasoning, tests, etc * Hence, we need a good reason to justify every mutable structure. » With this in minds, let’s go back to our model layer…

Slide 61

Slide 61 text

Immutable by Default Sometimes performance requires mutability 16 * At first approximation, mutability makes everything more difficult: reasoning, tests, etc * Hence, we need a good reason to justify every mutable structure. » With this in minds, let’s go back to our model layer…

Slide 62

Slide 62 text

Immutable by Default Sometimes performance requires mutability Sometimes an existing API is based on mutability 16 * At first approximation, mutability makes everything more difficult: reasoning, tests, etc * Hence, we need a good reason to justify every mutable structure. » With this in minds, let’s go back to our model layer…

Slide 63

Slide 63 text

Immutable by Default Sometimes performance requires mutability Sometimes an existing API is based on mutability Beware of premature optimisation! 16 * At first approximation, mutability makes everything more difficult: reasoning, tests, etc * Hence, we need a good reason to justify every mutable structure. » With this in minds, let’s go back to our model layer…

Slide 64

Slide 64 text

Immutable by Default Sometimes performance requires mutability Sometimes an existing API is based on mutability Beware of premature optimisation! Can you wrap the mutable API? 16 * At first approximation, mutability makes everything more difficult: reasoning, tests, etc * Hence, we need a good reason to justify every mutable structure. » With this in minds, let’s go back to our model layer…

Slide 65

Slide 65 text

Model Immutable 17 * In HfM, it was fairly straight forward to keep the model immutable. * NSFileWrappers for directories are mutable, but making them explicit in the model would have been awkward with Cabal’s representation anyway. * If you can’t make the model immutable, at least provide an immutable API (as, e.g., Swift arrays, dictionaries, and sets)

Slide 66

Slide 66 text

Model Immutable ✓ Cabal package in Haskell ✓ Source files as NSFileWrapper 17 * In HfM, it was fairly straight forward to keep the model immutable. * NSFileWrappers for directories are mutable, but making them explicit in the model would have been awkward with Cabal’s representation anyway. * If you can’t make the model immutable, at least provide an immutable API (as, e.g., Swift arrays, dictionaries, and sets)

Slide 67

Slide 67 text

Model Immutable ✓ Cabal package in Haskell ✓ Source files as NSFileWrapper Directories are not explicit in the model 17 * In HfM, it was fairly straight forward to keep the model immutable. * NSFileWrappers for directories are mutable, but making them explicit in the model would have been awkward with Cabal’s representation anyway. * If you can’t make the model immutable, at least provide an immutable API (as, e.g., Swift arrays, dictionaries, and sets)

Slide 68

Slide 68 text

Model Immutable ✓ Cabal package in Haskell ✓ Source files as NSFileWrapper Directories are not explicit in the model At least provide an immutable interface 17 * In HfM, it was fairly straight forward to keep the model immutable. * NSFileWrappers for directories are mutable, but making them explicit in the model would have been awkward with Cabal’s representation anyway. * If you can’t make the model immutable, at least provide an immutable API (as, e.g., Swift arrays, dictionaries, and sets)

Slide 69

Slide 69 text

View Model Hybrid 18 * Don’t copy model information — just reference it. It can’t change after all! * Swift: mutable methods in structs are like record update in Haskell (with builtin Lens-like syntax) * Transform to/from view format when information passes through.

Slide 70

Slide 70 text

View Model Hybrid struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … 18 * Don’t copy model information — just reference it. It can’t change after all! * Swift: mutable methods in structs are like record update in Haskell (with builtin Lens-like syntax) * Transform to/from view format when information passes through.

Slide 71

Slide 71 text

View Model Hybrid struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … Don’t copy 18 * Don’t copy model information — just reference it. It can’t change after all! * Swift: mutable methods in structs are like record update in Haskell (with builtin Lens-like syntax) * Transform to/from view format when information passes through.

Slide 72

Slide 72 text

View Model Hybrid struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … Don’t copy Use lets & structs 18 * Don’t copy model information — just reference it. It can’t change after all! * Swift: mutable methods in structs are like record update in Haskell (with builtin Lens-like syntax) * Transform to/from view format when information passes through.

Slide 73

Slide 73 text

View Model Hybrid struct Package { private var modelPackage: CBLPackage … var name: String { get { return modelPackage.name } set { modelPackage = CBLPackage(modelPackage, withName: newValue) } } … var richTextDesc: NSAttributedString{ get { return NSAttributedString(string: modelPackage.fullDescription) } set { modelPackage = CBLPackage(modelPackage, withFullDescription: newValue.string) } } … Don’t copy Use lets & structs class ProjectItem: NSObject { let category: ProjectItemCategory var identifier: String … weak var parent: ProjectItem? var children: [ProjectItem] var fileWrapper: NSFileWrapper? … } 18 * Don’t copy model information — just reference it. It can’t change after all! * Swift: mutable methods in structs are like record update in Haskell (with builtin Lens-like syntax) * Transform to/from view format when information passes through.

Slide 74

Slide 74 text

Time Series Changes as Streams of Values 19 » We need glue to (1) bind view state to view model state, but (2) without mutable variables.

Slide 75

Slide 75 text

25 Δt: 0s Mutable Variable 20 » Sampling a variable over time…

Slide 76

Slide 76 text

7 Δt: 1s Mutable Variable 21 » Sampling a variable over time…

Slide 77

Slide 77 text

11 Δt: 2s Mutable Variable 22 » Sampling a variable over time…

Slide 78

Slide 78 text

73 Δt: 3s Mutable Variable 23 » Sampling a variable over time…

Slide 79

Slide 79 text

42 Δt: 4s Mutable Variable 24 * The contents of the variable changes… » …in contrast to the value of a time series…

Slide 80

Slide 80 text

Δt 0 1 2 3 4 42 73 11 7 25 25 * The time series includes all values at once — it reifies time. * Can be regarded as a function over time, or an unbound stream of values. * FRP — popular ObjC/Swift library: ReactiveCocoa https://github.com/ReactiveCocoa/ ReactiveCocoa » Initially, no Swift version, so I wrote my own simple library ’Changes’…

Slide 81

Slide 81 text

Δt 0 1 2 3 4 42 73 11 7 25 ✓ Transform and compose (map, fold, etc) 25 * The time series includes all values at once — it reifies time. * Can be regarded as a function over time, or an unbound stream of values. * FRP — popular ObjC/Swift library: ReactiveCocoa https://github.com/ReactiveCocoa/ ReactiveCocoa » Initially, no Swift version, so I wrote my own simple library ’Changes’…

Slide 82

Slide 82 text

Δt 0 1 2 3 4 42 73 11 7 25 ✓ Transform and compose (map, fold, etc) ✓ Observe stream values (changes) 25 * The time series includes all values at once — it reifies time. * Can be regarded as a function over time, or an unbound stream of values. * FRP — popular ObjC/Swift library: ReactiveCocoa https://github.com/ReactiveCocoa/ ReactiveCocoa » Initially, no Swift version, so I wrote my own simple library ’Changes’…

Slide 83

Slide 83 text

Δt 0 1 2 3 4 42 73 11 7 25 ✓ Transform and compose (map, fold, etc) ✓ Observe stream values (changes) Related YLJ’15 talk FRP in Swift with ReactiveCocoa — Sebastian Grail 25 * The time series includes all values at once — it reifies time. * Can be regarded as a function over time, or an unbound stream of values. * FRP — popular ObjC/Swift library: ReactiveCocoa https://github.com/ReactiveCocoa/ ReactiveCocoa » Initially, no Swift version, so I wrote my own simple library ’Changes’…

Slide 84

Slide 84 text

protocol Observable: class { typealias Value // observed value typealias Observer = Value -> () // observer func func observeWithContext (context: Context, // determines lifetime observer: Context -> Observer) -> Observation … } 26 * Observable pairs observable values with matching observers * Changes — stream of observable, but ephemeral Changes * Variable — stream of values, where the last one is always available

Slide 85

Slide 85 text

protocol Observable: class { typealias Value // observed value typealias Observer = Value -> () // observer func func observeWithContext (context: Context, // determines lifetime observer: Context -> Observer) -> Observation … } class Changes: Observable { // ephemeral typealias Value = Change func announce(change: Change) … } class Variable: Observable { // last one persists typealias Value = T var value: T { didSet { …announce… } } … } 26 * Observable pairs observable values with matching observers * Changes — stream of observable, but ephemeral Changes * Variable — stream of values, where the last one is always available

Slide 86

Slide 86 text

protocol Observable: class { typealias Value // observed value typealias Observer = Value -> () // observer func func observeWithContext (context: Context, // determines lifetime observer: Context -> Observer) -> Observation … } class Changes: Observable { // ephemeral typealias Value = Change func announce(change: Change) … } class Variable: Observable { // last one persists typealias Value = T var value: T { didSet { …announce… } } … } class Changes: Observable { // ephemeral … } class Variable: Observable { // last one persists … } func map (source: Observed, f: Observed.Value -> Change) -> Changes 26 * Observable pairs observable values with matching observers * Changes — stream of observable, but ephemeral Changes * Variable — stream of values, where the last one is always available

Slide 87

Slide 87 text

27 * Stream of Package values connects the view model with the view layer.

Slide 88

Slide 88 text

public class ProjectViewModel: NSObject { var package: Variable = Variable(initialValue: …) var groupItems: ProjectItemGroups { get { return theGroupItems } } private lazy var theGroupItems: ProjectItemGroups = … … } stream of Package values 27 * Stream of Package values connects the view model with the view layer.

Slide 89

Slide 89 text

Three Principles for FP in a Stateful World mchakravarty TacticalGrace justtesting.org haskellformac.com 28

Slide 90

Slide 90 text

Thank you! 29

Slide 91

Slide 91 text

Wikimedia http://commons.wikimedia.org/wiki/File:Diopsis.jpg http://commons.wikimedia.org/wiki/File:Goldfields_Pipeline_SMC.JPG https://dribbble.com/shots/1667698-Free-vector-Macbook-Ipad-and-Iphone Free Image Sources http://commons.wikimedia.org/wiki/File:NeuSchwanstein_7.JPG https://en.wikipedia.org/wiki/File:HeTube.jpg http://commons.wikimedia.org/wiki/File:Stopwatch_A.jpg 30