Slide 1

Slide 1 text

SwiftUI ࣌୅ͷ Functional iOS Architecture 2020/09/21 iOSDC Japan 2020 Yasuhiro Inami / @inamiy

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

ɹhttps://speakerdeck.com/inamiy/reactive-state-machine-japanese

Slide 6

Slide 6 text

Reactive State Machine ͷৼΓฦΓ • MVVM ͔Β Redux / Elm Architecture (Mealy Machine) ΁ • Reducer = (Action, State) -> (State, Output) • Output = Publisher • ΞϓϦͷσʔλϑϩʔΛ୯ํ޲ͷϧʔϓʹ୯७Խ͠ɺঢ়ଶ؅ ཧͱςετΛ͠΍͘͢͢Δ • ෭࡞༻ (IO) ʹؔ਺ܕϦΞΫςΟϒϓϩάϥϛϯά (FRP) Λ༻ ͍Δ

Slide 7

Slide 7 text

Reactive State Machine ͷৼΓฦΓ • Proof of Concept • ReactiveAutomaton (ReactiveSwift൛) • RxAutomaton (RxSwift൛) • ͦͷଞ • React & Elm inspired frameworks in Swift • SwiftElmɿUIKit্ͷԾ૝ViewϑϨʔϜϫʔΫʢࢼݧ࣮૷ʣ

Slide 8

Slide 8 text

͋Ε͔Β4೥

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

SwiftUI Combine

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

Reactive State Machine ͷޙܧ࡞ʮHarvestʯΛΦʔϓϯιʔε

Slide 13

Slide 13 text

ࠓ೔ͷΞδΣϯμ SwiftUI ࣌୅ͷ Functional iOS Architecture • inamiy/Harvest • pointfreeco/swift-composable-architecture • bow-swift/bow-arch • 3ͭͷϑϨʔϜϫʔΫͷڞ௨఺ͱҧ͍ʹ͍ͭͯ • ReactɺElm ͳͲͷWebϑϩϯτΤϯυͱͷൺֱ

Slide 14

Slide 14 text

! Harvest

Slide 15

Slide 15 text

! Harvest • Reactive State Machine (Elm Architecture෩) ࣮૷Λվྑ • SwiftUI + Combine ରԠ (HarvestStore) • Dependency Injection ίϯςφͱͯ͠΋ಇ͘ • FRPʹΑΔ ෭࡞༻ͷΩϡʔ؅ཧ ͱΩϟϯηϧॲཧ • Optics (Lens & Prism) Λ࢖ͬͨ State ͱ Action ͷ෦඼Խͱ Reducer ͷ߹੒

Slide 16

Slide 16 text

෭࡞༻ΛΩϡʔͰ؅ཧ͢Δ • Publisher (Observable): ࣌ؒґଘͷ෭࡞༻ͷετϦʔϜ • ετϦʔϜͷετϦʔϜ ( Publisher> ) ͸ɺ ෭࡞༻ͷετϦʔϜΛʮΩϡʔ؅ཧʯ͍ͯ͠Δ͜ͱʹ૬౰ • Ωϡʔ؅ཧ͞Ε༷ͨʑͳετϦʔϜΛҰຊͷετϦʔϜʹ౷ ߹͢ΔʢʹϞφυ߹੒ɺϑϥοτԽʣ • Ωϡʔ؅ཧͷ ౷߹ઓུ (FlattenStrategy) • merge, concat, concurrent(max:), switchLatest, race ͳͲ

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

Elm Architecture + FRP Λ૊Έ߹ΘͤΔར఺ • FRPͷຊ࣭͸ɺ Publisher ಺෦ͷঢ়ଶΛӅṭ͠ͳ͕Βσʔλ ϑϩʔΛߏஙͰ͖Δ ͜ͱ • ͨͩ͠ɺঢ়ଶΛӅṭ͢Ε͹͢Δ΄Ͳɺঢ়ଶ؅ཧ͕೉͘͠ͳΔ • Elm Architecture ʢσʔλϑϩʔͷ؆қԽͱঢ়ଶ؅ཧͷ௥ ٻʣΛϕʔεʹɺFRP Ͱʮͭ·Βͳ͍ঢ়ଶ؅ཧʯΛল͘ • ྫɿ throttle ࣌ͷલճೖྗ࣌ࠁͷه࿥ɺલड़ͷΩϡʔ؅ ཧ͞Εͨ෭࡞༻ͷ౷߹ܭࢉͳͲ

Slide 20

Slide 20 text

Optics (Lens & Prism)

Slide 21

Slide 21 text

Optics (Lens & Prism) • Lens: ঢ়ଶʢ௨ৗ͸ struct ௚ੵܕʣʹର͢Δ2ͭͷૢ࡞ • ྫɿϢʔβʔ໊ͷऔಘ (get) ͱߋ৽ (set) • Prism: ΞΫγϣϯ (௨ৗ͸ enum ௚࿨ܕ) ʹର͢Δ2ͭͷૢ࡞ • ྫɿ֤ case ͔ΒίϚϯυੜ੒ & Φϓγϣϯऔಘ (tryGet) struct User { enum Command { var name: String case rm(rf: Bool) } }

Slide 22

Slide 22 text

struct Lens { /// struct ϝϯόม਺ͷऔಘ let get: (Whole) -> Part /// struct ϝϯόม਺ͷߋ৽ let set: (Whole, Part) -> Whole } struct Prism { /// enum case ͷ associated values ͷऔಘ let tryGet: (Whole) -> Part? /// case ؔ਺ʢenum ίϯετϥΫλʣ let build: (Part) -> Whole }

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

Lens ͱ Prism Λ࢖ͬͯ Reducerͷ ܕม׵ ʴ ߹੒͕Մೳ

Slide 37

Slide 37 text

Reducer ͕߹੒ՄೳͳΒ͹ ঢ়ଶͱΞΫγϣϯΛ ֤ίϯϙʔωϯτ͝ͱʹ ෼ղͯ͠ઃܭͰ͖Δ

Slide 38

Slide 38 text

/// Reducer ͷ ChildState Λ ਌ State ʹม׵ʢ൓มؔखʣ func contramapS (_ lens: Lens) // ਌͔Βࢠ΁ͷࣹ -> Reducer // ࢠ͔Β -> Reducer // ਌΁ͷࣹ /// Reducer ͷ ChildAction Λ ਌ Action ʹม׵ʢ൓มؔखʣ func contramapA (_ prism: Prism) // ਌͔Βࢠ΁ͷࣹ -> Reducer // ࢠ͔Β -> Reducer // ਌΁ͷࣹ

Slide 40

Slide 40 text

Optics ·ͱΊ • ΞϓϦͷ State (ओʹ struct) ͱ Action (ओʹ enum) Λڊେʹ ͤͣɺπϦʔߏ଄ʹ෼ղͯ͠ɺݸʑͷίϯϙʔωϯτ͝ͱʹ ؅ཧ͢Δʢૄ݁߹Խʣ • ݸʑͷίϯϙʔωϯτͷ Reducer Λશମʹ·ͱΊΔ ࡍʹ Lens ͱ Prism ͕׆༂͢Δ (react-reduxͷ্Ґ൛) • Optics ͸ ؔ਺ܕϓϩάϥϛϯάͱݍ࿦ Λ࢖ͬͨ୅දతͳς ΫχοΫͷ1ͭ

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

Harvest-SwiftUI- Gallery https://github.com/inamiy/Harvest-SwiftUI-Gallery

Slide 45

Slide 45 text

Composable Architecture

Slide 46

Slide 46 text

Composable Architecture (TCA) • Point-Free νʔϜʹΑΔ Elm Architecture ෩ͷ࣮૷ • Multi-Storeํࣜɿ ࠷্ҐͰ͸ͳ͘ɺ਌ʢ্ྲྀʣͱࢠʢԼ ྲྀʣίϯϙʔωϯτ֤ʑʹରͯ͠ϦΞΫςΟϒʹΠϕϯτ Λ఻ൖ͢Δ ʴ ॏෳ๷ࢭॲཧ • swift-case-paths Λ࢖ͬͨ Prism ࣮૷ • Lens ͸Swiftඪ४ͷ WritableKeyPath Λ࢖ͬͯ୅༻ • ˑ2000Ҏ্ɺυΩϡϝϯτͱϏσΦνϡʔτϦΞϧ͕ॆ࣮

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

Case Paths struct User { var name: String } // WritableKeyPath let keyPath = \User.name // όοΫεϥογϡ enum Command { case rm(rf: Bool) } // CasePath let casePath = /Command.rm // ௨ৗͷεϥογϡ

Slide 53

Slide 53 text

struct CasePath { // `Prism` ͱಉܕ let embed: (Value) -> Root let extract: (Root) -> Value? } prefix func / ( embed: @escaping (Value) -> Root ) -> CasePath { /* ! Magic inside */ } " prefix func / " ͷ಺෦࣮૷ Swift ͷϦϑϨΫγϣϯΛ࢖ͬͯɺembedʢcaseؔ਺ʣ͔Β extract Λࣗಈతʹಋग़͢Δ (ར఺ɿcodegen͕ཁΒͳ͍)

Slide 54

Slide 54 text

ৄࡉ͸ͪ͜ΒͷηογϣϯΛ͝ཡ͍ͩ͘͞

Slide 55

Slide 55 text

Bow Arch

Slide 56

Slide 56 text

Bow Arch • Tomás Ruiz-López ࢯ (47 Degrees ࣾ) ࡞ͷ UI Architecture • Bow: Lightweight Higher Kinded Polymorphism (ߴΧΠϯυ ଟ૬) Λ࢖ͬͨؔ਺ܕϓϩάϥϛϯά༻ϥΠϒϥϦ • func foo ͷΑ͏ͳॻ͖ํ͕Ͱ͖Δ • ࢀߟɿSwiftͰߴΧΠϯυଟ૬ - Speaker Deck • Comonadic UI: ݍ࿦ʢ਺ֶʣΛ࢖ͬͨUIઃܭख๏

Slide 57

Slide 57 text

Comonadic UI

Slide 58

Slide 58 text

ίϞφυ ≈ ΦϒδΣΫτࢦ޲ − Մมࢀর • SwiftUI.View Λ ίϞφυ ͱͯ͠ߟ͑Δ • ίϞφυ: (಺෦)ঢ়ଶΛ࣋ͪɺঢ়ଶ͔Βܭࢉͨ݁͠ՌΛฦ͢ • ྫɿΠςϨʔλ͸ɺ಺෦ঢ়ଶΛߋ৽͠ͳ͕Β next Λग़ྗ • ྫɿϏϧμʔ͸ɺड͚औͬͨύϥϝʔλΛ಺෦ঢ়ଶʹอ࣋ ͯ͠ɺ࠷ऴ݁ՌΛग़ྗ • ྫɿReact Component (SwiftUI) ͸ɺঢ়ଶΛ࣋ͪͭͭɺ render (body) ͰԾ૝DOM (View) Λग़ྗ

Slide 59

Slide 59 text

struct Component: View { // ݱࡏͷঢ়ଶ var state: S // ݱࡏͷঢ়ଶ͔ΒԾ૝ViewΛܭࢉ let _body: (S) -> V // Note: static var Ͱߟ͑Δͱɺܕ͸ `Self -> V` var body: V { _body(state) } } Component = W ͱ͓͘ͱɺ body: W -> V ɾɾɾ ίϞφυʹॏཁͳ extract ͷੑ࣭

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

No content

Slide 63

Slide 63 text

No content

Slide 64

Slide 64 text

// Ϟφυ M = UFʢίϯςΩετΛੜ੒͢Δܭࢉʣɹɹɹ// NOTEɿٙࣅSwift protocol Monad[M] where Functor[M] { static func `return`(_ c: C) -> M // η = unit static func join(_ mmc: M>) -> M // static func flatMap(_ f: C -> M) // -> M -> M } // ίϞφυ W = FUʢίϯςΩετΛফඅ͢Δܭࢉʣ protocol Comonad[W] where Functor[W] { static func extract(_ wd: W) -> D // ε = counit static func duplicate(_ wd: W) -> W> // static func extend(_ f: W -> D2) // -> W -> W }

Slide 65

Slide 65 text

ίϞφυ (Comonad) // ٙࣅSwift protocol Comonad[W] where Functor[W] { static func extract(_ wd: W) -> D static func duplicate(_ wd: W) -> W> } • extract: ΦϒδΣΫτ W ͔ΒίϯςΩετΛফඅͯ͠ D Λग़ྗʢe.g. ঢ়ଶΛ࢖ͬͯ View Λग़ྗʣ • duplicate: ΦϒδΣΫτͷऔΓ͏ΔະདྷਤΛੜ੒ʢޙड़ʣ

Slide 66

Slide 66 text

duplicate ͷΠϝʔδʢྫɿແݶετϦʔϜʣ let stream = [ 0, 1, 2, ... ] // ݱ࣌఺ͷແݶετϦʔϜ // ʢݱࡏͱະདྷͷʣແݶετϦʔϜΛཁૉʹ࣋ͭແݶετϦʔϜ duplicate(stream) = [ [ 0, 1, 2, ... ], // ݱࡏͷ `stream` Λෳ੡ [ 1, 2, 3, ... ], // ෳ੡ + shift [ 2, 3, 4, ... ], // ෳ੡ + shift 2ճ [ 3, 4, 5, ... ], // ෳ੡ + shift 3ճ ... ]

Slide 67

Slide 67 text

duplicate ͷΠϝʔδʢྫɿSwiftUI / Reactʣ let makeComp: (S) -> Component = Component(_body: ...) // ෦෼ద༻ let component: Component = makeComp(state: ...) // ݱࡏͷ Component // ʢݱࡏͱະདྷͷʣComponent Λੜ੒͢Δ Component duplicate(component) = Component(_body: makeComp, state: component.state) ≈ [ /* ݱࡏͷ Component ͷෳ੡ */, /* ෳ੡ + ঢ়ଶͷҰ෦͕มߋ͞Εͨ Component */, /* ෳ੡ + ঢ়ଶͷผͷҰ෦͕มߋ͞Εͨ Component */, ... ] // Component ͕औΓ͏Δશͯͷঢ়ଶͷۭؒ

Slide 68

Slide 68 text

Component ≅ Store ίϞφυ struct Component { // ݱࡏͷঢ়ଶ var state: S // ݱࡏͷঢ়ଶ͔ΒԾ૝ViewΛܭࢉ let _body: (S) -> V } struct Store { let state: S let render: (S) -> A }

Slide 69

Slide 69 text

࣮ࡍͷ ComponentʢΠϕϯτϋϯυϥ෇͖ʣ struct Component { // ݱࡏͷঢ়ଶ var state: S // ݱࡏͷঢ়ଶͱʮΠϕϯτϋϯυϥʯΛ౉ͯ͠Ծ૝ViewΛܭࢉ let view: (S) -> (EventHandler) -> V } typealias EventHandler = (Action) -> IO /* ෭࡞༻ */

Slide 70

Slide 70 text

͜͜Ͱɺ typealias UI = (EventHandler) -> V ͱ͓͘ͱɺ struct Component { var state: S let view: (S) -> UI } Component ͸ Store> ͱ͍͏ܗͰද͞ΕΔ

Slide 71

Slide 71 text

ίϞφυͷ಺෦ঢ়ଶΛ֎͔Βૢ࡞͢Δ ઌ΄ͲͷແݶετϦʔϜͷྫͰ͸ɺ shift ʢ0, 1, 2, l߭Ďůሑ Ⅲ⴬۷ƑҠቔƎཌྷ֒čǸǠǟƵ൐ƆƂDžƾȀDSLͰදͤΔʣ // ແݶετϦʔϜʢίϞφυʣ // Shiftૢ࡞ʢϞφυʣ indirect enum Stream { indirect enum Shift { case cons(A, Stream) case done(A) } case shift(Shift) } Q. ͜ΕΒ2ͭͷܕ͸ͲͷΑ͏ͳؔ܎ʹ͋Δͷ͔ʁ

Slide 72

Slide 72 text

Slide 73

Slide 73 text

Pairing Λ࢖͏ͱɺϞφυͰද͞ΕΔঢ়ଶૢ࡞ʹΑͬͯɺίϞ φυͷະདྷΛܾΊΔ͜ͱ͕Ͱ͖Δɻ // `stream` ͷະདྷΛ `shift` ͰܾΊΔ func select(shift: Shift<()>, stream: Stream) -> Stream { pair({ _, stream in stream })(shift)(duplicate(stream)) } // Ұൠతʹɺ೚ҙͷϞφυɾίϞφυͷϖΞʹ͍ͭͯ੒Γཱͭ func select(monad: M<()>, comonad: W) -> W where Monad[M], Comonad[W], Pairing[M, W] { pair({ _, comonad in comonad })(monad)(duplicate(comonad)) }

Slide 74

Slide 74 text

ͳ͓ɺ SwiftUI ্ͷ ComponentʢStore ίϞφυʣͷ৔߹ɺঢ় ଶૢ࡞ͱͯ͠ State ϞφυΛ࢖͏͜ͱ͕Ͱ͖Δʢཧ༝͸ޙड़ʣ struct Store { let state: S let render: (S) -> A } struct State { let runState: S -> (A, S) } extension Pairing[State, Store] { ... }

Slide 75

Slide 75 text

Stream ίϞφυ → Shift Ϟφυ Store ίϞφυ → State Ϟφυ Q. ίϞφυͷϖΞͱͳΔϞφυ͸ ͲͷΑ͏ʹݟ͚ͭΔͷ͔ʁ

Slide 76

Slide 76 text

// ݍ࿦Ͱݴ͏ɺComonadʹԊͬͨ߃౳ؔखͷӈKan Liftɻ // ೚ҙͷίϞφυ `W` ʹରԠ͢Δʢঢ়ଶૢ࡞ͷʣϞφυ `Co` Λߏ੒͢Δ͜ͱ͕Մೳɻ struct Co { let runCo: W R> -> R } extension Monad[Co] where Comonad[W] { static func `return`(_ c: C) -> Co { Co { wf in W.extract(wf)(c) } } static func join(_ mmc: Co>) -> Co Co { (wc2r: W R>) in mmc.runCo( W.extend({ wc2r in { (mc: Co) in mc.runCo(wc2r) } })(wc2r) ) } } }

Slide 78

Slide 78 text

͜͜·Ͱͷ੔ཧ (Comonadic UI) • ίϞφυͷ extract ʹΑͬͯɺঢ়ଶ͔ΒViewΛੜ੒͢Δ • ίϞφυͷ duplicate ʹΑͬͯɺUIͷະདྷਤΛ࡞Δ • ίϞφυͷϖΞͱͳΔ ঢ়ଶૢ࡞༻ͷϞφυΛ Co Ͱࢦ ఆ ͢Δ • select ͰίϞφυͱঢ়ଶૢ࡞༻ϞφυͷϖΞ͔Βɺ ະདྷͷ UI༻ίϞφυΛબ୒͢Δ

Slide 79

Slide 79 text

ίϞφυ × ෭࡞༻ (IO) // ίϞφυΛϥοϓͯ͠ɺະདྷબ୒ͱ෭࡞༻ͷ࣮ߦʢՄมࢀরͷߋ৽ΛؚΉʣΛߦ͏ class EffectComponent: ObservableObject where Comonad[W] { @Published var comonad: W> func explore() -> V { W.extract(comonad) { (action: IO>) in action.flatMap { (monad: Co) in let nextComonad = select(monad, self.comonad.duplicate()) return IO.invoke { self.comonad = nextComonad } } } } }

Slide 80

Slide 80 text

ίϞφυ × ෭࡞༻ = ΦϒδΣΫτࢦ޲ϓϩάϥϛϯά (OOP) • EffectComponent ͸ OOPʹ͓͚ΔʮΦϒδΣΫτʯ ʢͦͷෳࡶ͞ΛʮίϞφυʯͱʮ෭࡞༻ʯʹ෼ղ͢Δʣ • W = Store ίϞφυͷ৔߹ɺ ϖΞͱͳΔ ঢ়ଶϞφυͱͦΕʹ ൐͏෭࡞༻͸ɺ setState ʢঢ়ଶͷʮ௚઀ߋ৽ʯʣͱ౳Ձ • React ΍ SwiftUIʢ@State ͷՄมࢀরʣͷੈք؍ͱҰக • Note: ίϯϙʔωϯτͷωετ͸ɺίϞφυม׵ࢠΛ࢖͏

Slide 81

Slide 81 text

Q. EffectComponent ͸ɺ ଞͷίϞφυ W ʹ΋࢖͑ΔͷͰ͸ʁ !

Slide 82

Slide 82 text

Moore ίϞφυ indirect enum Moore { // I = ೖྗɺ A = ग़ྗ // ݱࡏͷग़ྗͱɺʮೖྗ͔ΒະདྷͷMooreίϞφυʯͷੜ੒ؔ਺ case runMoore(A, I -> Moore) } ∃S. (initial: S, reducer: S -> I -> S, render: S -> A) ͱಉܕ (Moore State Machineɺঢ়ଶͷʮؒ઀ߋ৽ʯ) ࣮૷ྫɿ Elm Architecture, Redux

Slide 83

Slide 83 text

༨ࣗ༝ίϞφυ (Cofree) // ೚ҙͷؔख `F` ʹରͯ͠ɺίϞφυΛ࡞Δ͜ͱ͕Ͱ͖Δɻ // `F(X) = I -> X` ͷͱ͖ɺMooreɻ`F(X) = ()` ͷͱ͖ɺ㱽S.Storeɻ indirect enum Cofree { case runCofree(A, F>) } ϖΞͱͳΔࣗ༝Ϟφυ (Free) ͕ΫΤϦDSLʹͳΔ ࣮૷ྫɿ PureScript Halogen

Slide 84

Slide 84 text

Comonad → Architecture Store → React Moore → Elm Cofree → PureScript

Slide 85

Slide 85 text

ίϞφυ͸ ΞʔΩςΫνϟʔΛ نఆ͢Δ

Slide 86

Slide 86 text

No content

Slide 87

Slide 87 text

·ͱΊ

Slide 88

Slide 88 text

·ͱΊ • SwiftUI ͷຊ࣭͸ ʮίϞφυʯ • ίϞφυͷߏ଄͕ UIΞʔΩςΫνϟʔͷύλʔϯ ΛܾΊΔ • React, Elm, PureScript Halogen, etc... • ঢ়ଶɺΞΫγϣϯɺ Reducer Λ֤ίϯϙʔωϯτ͝ͱʹ෼ղ ͠ɺ Optics Λ࢖ͬͯ·ͱΊ্͛Δ • ؔ਺ܕϓϩάϥϛϯάͱݍ࿦ɿ ຊ࣭Λཧղ͢Δڧྗͳख๏

Slide 89

Slide 89 text

Harvest TCA Bow Arch GitHub Stars ˑ 300 ˑ 2000 ˑ 100 ࡞ऀͷ΍Δؾ ❓ ೉қ౓ Medium Medium Hard ෭࡞༻ Combine Combine BowEffects Optics FunOptics WritableKeyPath & CasePaths BowOptics Comonadic UI Moore Moore Any Comonads ӨڹΛड͚ͨݴޠ Elm Elm & React PureScript & ݍ࿦

Slide 90

Slide 90 text

References (Libraries & Optics) • ! Harvest: Apple's Combine.framework + State Machine, inspired by Elm • Composable Architecture • bow-arch: Comonadic UIs • Brandon Williams - Lenses in Swift • Lenses and Prisms in Swift: a pragmatic approach | Fun iOS

Slide 91

Slide 91 text

References (Comonadic UI) • Declarative UIs are the Future — And the Future is Comonadic! • The Future Is Comonadic! - Speaker Deck • Comonads for user interfaces - Arthur Xavier • A Real-World Application with a Comonadic User Interface • The Comonad.Reader » Monads from Comonads

Slide 92

Slide 92 text

References (෬ઢճऩ) • Reactive State Machine (Japanese) - Speaker Deck • SwiftͰElmΛ࡞Δ (Japanese) - Speaker Deck • SwiftͰߴΧΠϯυଟ૬ - Speaker Deck • ݍ࿦ͱSwift΁ͷԠ༻ / iOSDC Japan 2018 - Speaker Deck • ϓϩάϥϚͷͨΊͷϞφυ(ݍ࿦) - Speaker Deck • ݍ࿦ͱϓϩάϥϛϯά - Speaker Deck

Slide 93

Slide 93 text

Thanks! Yasuhiro Inami @inamiy