Slide 1

Slide 1 text

Swift async/await Λࢧ͑Δ Ϟφυɺܧଓɺ ίϧʔνϯ 2021/09/18 iOSDC Japan 2021 Yasuhiro Inami / @inamiy

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

ඇಉظܭࢉ

Slide 4

Slide 4 text

ίʔϧόοΫํࣜʹΑΔඇಉظܭࢉ func fetch( request: Request, completion: @escaping (Result) -> Void ) { let task = URLSession.shared .dataTask(with: request) { data, response, error in if let error = error { completion(.failure(error)) } decode(data, completion: { response in completion(.success(response)) }) } task.resume() }

Slide 5

Slide 5 text

ίʔϧόοΫ஍ࠈ fetch1(request1) { response1 in fetch2(response1) { response2 in fetch3(response2) { response3 in fetch4(response3) { response4 in fetch5(response4) { response5 in print(response5) } } } } }

Slide 6

Slide 6 text

ϦΞΫςΟϒɾϓϩάϥϛϯάʹΑΔඇಉظܭࢉ func fetch(request: Request) -> Observable { Observable.create { completion in let task = URLSession.shared .dataTask(with: request) { data, response, error in if let error = error { completion(.failure(error)) } decode(data, completion: { response in completion(.success(response)) }) } task.resume() return Disposables.create { task.cancel() } } }

Slide 7

Slide 7 text

qBU.BQʹΑΔϝιουνΣʔϯʢ஍ࠈʁʣ fetch1(request1) .flatMap { response1 in fetch2(response1) } .flatMap { response2 in fetch3(response2) } .flatMap { response3 in fetch4(response3) } .flatMap { response4 in fetch5(response4) } .subscribe(onNext: { response5 in print(response5) })

Slide 8

Slide 8 text

BTZODBXBJUʹΑΔඇಉظܭࢉ func fetch(request: Request) async throws -> Response { let (data, _) = try await URLSession.shared.data(with: request) return try JSONDecoder() .decode(Response.self, from: data) } BTZODΩʔϫʔυ BXBJUΩʔϫʔυͰ ඇಉظܭࢉΛ଴ͭ

Slide 9

Slide 9 text

BTZODBXBJUʹΑΔʮखଓ͖ܕϓϩάϥϛϯάʯ Task.detached { let response1 = try await fetch1(request1) let response2 = try await fetch2(response1) let response3 = try await fetch3(response2) let response4 = try await fetch4(response3) let response5 = try await fetch5(response4) print(response5) }

Slide 10

Slide 10 text

ඇಉظܭࢉ͍Ζ͍Ζ wίʔϧόοΫํࣜ w1SPNJTF'VUVSFɺϦΞΫςΟϒɾϓϩάϥϛϯά wBTZODBXBJU खଓ͖ ࣮͸ͲΕ΋ಉ͡Α͏ͳ΋ͷͱΈͳͤΔʂ

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

ؔ਺ܕϓϩάϥϛϯά ࡾॐ࢜Λ࿈ΕͯདྷͨΑ

Slide 13

Slide 13 text

୯ͳΔࣗݾؔखͷݍʹ͓͚Δ ϞϊΠυର৅ͩΑ ܧଓJTύϫʔ ڠௐతͳൃදΛ໨ࢦͯ͠ ͕Μ͹Γ·͢ Ϟφυ ܧଓ ίϧʔνϯ

Slide 14

Slide 14 text

୯ͳΔࣗݾؔखͷݍʹ͓͚Δ ϞϊΠυର৅ͩΑ ܧଓJTύϫʔ ڠௐతͳൃදΛ໨ࢦͯ͠ ͕Μ͹Γ·͢ Ϟφυ ܧଓ ίϧʔνϯ ʲ͓அΓʳ ٙࣅ4XJGUίʔυΛ࢖͍·͢

Slide 15

Slide 15 text

Ϟφυ Monad ! ju" a monoid in # category of endofunctors

Slide 16

Slide 16 text

J04%$ ݍ࿦ͱ4XJGU΁ͷԠ༻ IUUQTTQFBLFSEFDLDPNJOBNJZJPTEDKBQBO ϓϩάϥϚͷͨΊͷݍ࿦ษڧձ ϓϩάϥϚͷͨΊͷϞφυ ݍ࿦ IUUQTTQFBLFSEFDLDPNJOBNJZOVNCFSDBUQH

Slide 17

Slide 17 text

Ϟφυ J04%$ΑΓ protocol Monad[M] where Functor[M] { static func unit(_ c: C) -> M static func join(_ mmc: M>) -> M } extension Monad { static func init_() -> M { .unit(()) } static func flatMap(_ f: C -> M) -> M -> M { return { .join(map(f)($0)) } } } 'VODUPS ؔख ͷTVCQSPUPDPM 'VODUPS͸NBQΛ࣋ͭ Ϟφυ͸͞Βʹ VOJUPSJOJU@ KPJOPSqBU.BQ Λ࣋ͭ

Slide 18

Slide 18 text

Ϟφυͷྫɿ0QUJPOBM enum Optional { case none case some(T) init(_ some: T) // unit: T -> Optional func map(_ transform: (T) -> U) -> U? func flatMap(_ transform: (T) -> U?) -> U? } VOJU NBQ qBU.BQΛ࣋ͭͷͰɺ 0QUJPOBM͸Ϟφυ

Slide 19

Slide 19 text

Ϟφυͷྫɿ"SSBZ struct Array { init() // init_: () -> Array func map(_ transform: (T) -> U) -> [U] func flatMap(_ transform: (T) -> [U]) -> [U] } JOJU@ NBQ qBU.BQΛ࣋ͭͷͰɺ "SSBZ͸Ϟφυ

Slide 20

Slide 20 text

Ϟφυͷྫɿ3Y0CTFSWBCMF struct Observable { // unit: T -> Observable static func just(_ element: T) func map(_ transform: (T) -> U) -> Observable func flatMap(_ transform: (T) -> Observable) -> Observable } VOJU NBQ qBU.BQΛ࣋ͭͷͰɺ 0CTFSWBCMF͸Ϟφυ

Slide 21

Slide 21 text

Ϟφυଇ // ࠨ୯Ґݩ unit(a).flatMap(f) == f(a) // ӈ୯Ґݩ monad.flatMap(unit) == monad // ݁߹཯ monad.flatMap(f).flatMap(g) == monad.flatMap { f($0).flatMap(g) }

Slide 22

Slide 22 text

Ϟφυଇͷ݁߹཯ // ݁߹཯ monad .flatMap(f) .flatMap(g) == monad.flatMap { f($0).flatMap(g) }

Slide 23

Slide 23 text

Ϟφυଇͷ݁߹཯ // ݁߹཯ͷࠨล monad .flatMap(f) .flatMap(g) .flatMap(h) .flatMap(i) .flatMap(j) // ݁߹཯ͷӈล monad.flatMap { f($0).flatMap { g($0).flatMap { h($0).flatMap { i($0).flatMap { j($0) } } } } } ==

Slide 24

Slide 24 text

Ϟφυ͸ ίʔϧόοΫ஍ࠈΛ ϝιουνΣʔϯʹม׵͢Δ

Slide 25

Slide 25 text

qBU.BQνΣʔϯͷྫɿ0QUJPOBM$IBJOJOH let monad: Optional = … let bar = monad?.is?.just?.a?.monoid monad ?.is ?.just ?.a ?.monoid monad .flatMap { $0.is } .flatMap { $0.just } .flatMap { $0.a } .flatMap { $0.monoid } ==

Slide 26

Slide 26 text

qBU.BQνΣʔϯͷྫɿ0QUJPOBM$IBJOJOH monad ?.is ?.just ?.a ?.monoid monad .flatMap(\.is) .flatMap(\.just) .flatMap(\.a) .flatMap(\.monoid) == let monad: Optional = … let bar = monad?.is?.just?.a?.monoid 4& ,FZ1BUI&YQSFTTJPOT BT'VODUJPOT

Slide 27

Slide 27 text

0QUJPOBM$IBJOJOHͷʮʁʯ͸ qBU.BQ ,FZ1BUI HFUUFS

Slide 28

Slide 28 text

qBU.BQνΣʔϯͷྫɿ3FTVMU let monad: Result = … let bar = monad?.is?.just?.a?.monoid monad .flatMap { $0.is } .flatMap { $0.just } .flatMap { $0.a } .flatMap { $0.monoid } 3FTVMUʹ͸0QUJPOBMͷΑ͏ͳ ઐ༻ͷ౶ҥߏจ͕ͳ͍ 2ϕλʹqBU.BQνΣʔϯ͢Δ Ҏ֎ͷॻ͖ํ͸͋Δ͔ʁ

Slide 29

Slide 29 text

UISPXTUSZΛ࢖ͬͨखଓ͖ var monad: Foo { get throws { ... } } func procedure() throws -> Bar { let monad_ = try monad let is_ = try monad_.is let just_ = try is_.just let a_ = try is_.a let monoid_ = try is_.monoid return monoid_ } 4& &⒎FDUGVM3FBEPOMZ 1SPQFSUJFT 4XJGU "5ISPXJOHGVODUJPOΛ࢖͏ ʢ஫ҙɿΤϥʔܕ෇͚͕ऑ͘ͳΔʣ USZΩʔϫʔυ͕ 0QUJPOBM$IBJOJOHʹ͓͚ΔA Aʹ૬౰

Slide 30

Slide 30 text

2ඇಉظܭࢉ΋ಉ͡࿮૊ΈͰ ߟ͑Δ͜ͱ͕Ͱ͖Δʁ ˣ "ͦΕ͕BTZODBXBJU

Slide 31

Slide 31 text

qBU.BQνΣʔϯͷྫɿ"TZOD let monad: Async = … monad .flatMap { $0.is } .flatMap { $0.just } .flatMap { $0.a } .flatMap { $0.monoid } "TZODඇಉظϞφυ͕ ͋ΔͱԾఆ͢Δ 1SPNJTF'VUVSF0CTFSWBCMF ͱಉ͡ͱࢥͬͯྑ͍ 2ϕλʹqBU.BQνΣʔϯ͢Δ Ҏ֎ͷॻ͖ํ͸͋Δ͔ʁ

Slide 32

Slide 32 text

BTZODBXBJUΛ࢖ͬͨखଓ͖ var monad: Foo { get async { ... } } func procedure() async -> Bar { let monad_ = await monad let is_ = await monad_.is let just_ = await is_.just let a_ = await is_.a let monoid_ = await is_.monoid return monoid_ } UISPXTUSZΛ BTZODBXBJUΩʔϫʔυʹஔ͖׵͑Δ͚ͩ ""TZODGVODUJPOΛ࢖͏

Slide 33

Slide 33 text

͜͜·Ͱͷ·ͱΊʢϞφυʣ wϞφυɿNBQVOJUqBU.BQ Ϟφυଇ wϞφυ݁߹཯ɿίʔϧόοΫ஍ࠈΛϝιουνΣʔϯʹม׵ w0QUJPOBMɿqBU.BQ˱A Aԋࢉࢠ w3FTVMUɿqBU.BQ˱USZΩʔϫʔυ w"TZODɿqBU.BQ˱BXBJUΩʔϫʔυ ʮϞφυʯͱ ʮݴޠ࢓༷ ʢखଓ͖ͱΩʔϫʔυʣʯ ʹରԠؔ܎͕͋Δʂ

Slide 34

Slide 34 text

ܭࢉޮՌ Computational Effect

Slide 35

Slide 35 text

ܭࢉޮՌͱ͸ʁ ܭࢉޮՌʹܭࢉͷաఔͰ௥ՃͰൃੜ͢Δ ෭ ࡞༻ ϞφυʹΑΔܭࢉޮՌ wqBU.BQʢ೚ҙͷܭࢉޮՌʹରͯ͠ڞ௨ͷ໊લʣ ݴޠ࢓༷ खଓ͖ʷ੍ޚԋࢉࢠʣʹΑΔܭࢉޮՌ wA A UISPXTUSZ BTZODBXBJUͳͲ ֤ʑͷܭࢉޮՌʹରͯ͠ҟͳΔ໊લ

Slide 36

Slide 36 text

ܭࢉޮՌͷྫ wΤϥʔϋϯυϦϯά 3FTVMU UISPXTUSZ wඇಉظܭࢉ "TZOD1SPNJTF0CTFSWBCMF BTZODBXBJU wঢ়ଶߋ৽ 4UBUF wඇܾఆੑܭࢉ "SSBZ ͳͲ

Slide 37

Slide 37 text

2Ϟφυͱݴޠ࢓༷ͷ ΪϟοϓΛຒΊΔʹ͸ʁ

Slide 38

Slide 38 text

EPه๏ do-notation

Slide 39

Slide 39 text

࠶ܝɿqBU.BQνΣʔϯͷྫɿ3FTVMU let monad: Result = … monad .flatMap { $0.is } .flatMap { $0.just } .flatMap { $0.a } .flatMap { $0.monoid }

Slide 40

Slide 40 text

3FTVMUͷEPه๏ʹΑΔखଓ͖Խ var monad: Foo { get throws { ... } } Result.do { monad_ <- monad is_ <- monad_.is just_ <- is_.just a_ <- just_.a monoid_ <- a_.monoid return monoid_ } 3FTVMU༻ͷEPείʔϓΛ࡞Γɺ AAΛqBU.BQʹݟཱͯɺ ଋറม਺Λࠨଆʹஔ͘ EPه๏qBU.BQνΣʔϯΛ खଓ͖ॲཧʹݟͤΔ౶ҥߏจ

Slide 41

Slide 41 text

"TZODͷEPه๏ʹΑΔखଓ͖Խ var monad: Foo { get async { ... } } Async.do { monad_ <- monad is_ <- monad_.is just_ <- is_.just a_ <- just_.a monoid_ <- a_.monoid return monoid_ } "TZOD༻ͷEPείʔϓΛ࡞Γɺ AAΛqBU.BQʹݟཱͯɺ ଋറม਺Λࠨଆʹஔ͘

Slide 42

Slide 42 text

Ϟφυ͸ EPه๏ʹΑͬͯ खଓ͖ॲཧʹมܗͰ͖Δ ˣ 2Ϟφυͱݴޠ࢓༷͸ͲͪΒ΋ ʮखଓ͖ʯͱΈͳͤΔͷͰಉ͡ʁ

Slide 43

Slide 43 text

Ϟφυͷ໰୊఺ɿܭࢉޮՌͷ߹੒ var monad: Foo { get async throws { ... } } // try await ͨ͠Γɺtry or await ୯ମݺͼग़͠΋Ͱ͖Δɻ func procedure() async throws -> Bar { let monad_ = try await monad let is_ = await monad_.is let just_ = await is_.just let a_ = try just_.a let monoid_ = await a_.monoid return monoid_ } BTZODUISPXTͷ߹੒

Slide 44

Slide 44 text

// Ϟφυ͕ෳ਺ʹωετ͍ͯ͠Δ৔߹ɺ߹੒ܭࢉͷѻ͍͕େม let monad: Async> = … // AsyncResult.do ͱ͸؆୯ʹॻ͚ͳ͍ͷͰɺͻͱ·ͣ Async.do Λ࢖ͬͯΈΔ Async.do { // `<-` ͸͋͘·Ͱ Async.flatMap ʢResult.flatMap ͸Ͱ͖ͳ͍ʣ monadResult <- monad // ͜ͷdoείʔϓͰ͸Resultͷத਎ΛऔΓग़͢ํ๏͕ͳ͍ͷͰɺ // get()! Ͱڧ੍తʹߦ͏ ʹ ΤϥʔϋϯυϦϯάʹͳ͍ͬͯͳ͍ɻ // ·ͨɺ಺෦Ͱ Result.do Λ࢖ͬͯ΋͏·͍͔͘ͳ͍ɻ let monad_ = monadResult_.get()! is_ <- monad_.is just_ <- is_.just a_ <- just_.a.get()! monoid_ <- a_.monoid return monoid_ } ͜ͷ΍ΓํͰ͸ɺ3FTVMUपΓͷ ΤϥʔϋϯυϦϯά্͕ख͘දݱͰ͖ͳ͍ ˣ Ϟφυ͸ѻ͍ʹ͍͘ʂ

Slide 45

Slide 45 text

Ϟφυͷ߹੒໰୊ʹର͢Δղܾࡦ͍Ζ͍Ζ wϞφυม׵ࢠ .POBE5SBOTGPSNFS w5BHMFTT'JOBM wࣗ༝Ϟφυ$PQSPEVDU ؔखͷ௚࿨ w&YUFOTJCMF&GGFDU wࣗ༝Ϟφυ0QFO6OJPO w$PZPOFEB ༨ถా ࣗ༝Ϟφυ0QFO6OJPO

Slide 46

Slide 46 text

ࣗ༝Ϟφυ 'SFF.POBE // ࣗ༝Ϟφυɿunit ͱ join ͕࠶ؼతσʔλߏ଄಺ʹఆٛ͞Ε͍ͯΔ indirect enum Free { case unit(A) case join(F>) } extension Monad[Free] where Functor[F] { func flatMap(_ f: A -> Free) -> Free { switch self { case let .unit(a): return f(a) case let .join(x): return .join(x.map { $0.flatMap(f) }) } } } ؔख'Λ༩͑Δͱɺͦͷߏ଄ʹରԠͨ͠ ΠΠײ͡ͷϞφυ͕खʹೖΔ

Slide 47

Slide 47 text

// try & await ੍ޚԋࢉࢠΛߏ੒͢Δϕʔεؔख // NOTE: `Value -> Next` ͕ίʔϧόοΫʹ૬౰ enum AsyncThrowsF { // NOTE: ͸ case಺δΣωϦΫεʢٙࣅSwiftʣ case try_(Result, Value -> Next) case await_(Async, Value -> Next) } // async + throws ͷ྆ํʹରԠ͢ΔϞφυʢࣗ༝Ϟφυʴϕʔεؔख͔Β࡞੒ʣ typealias AsyncThrows = Free // try ΩʔϫʔυΛࣗ࡞ func try_(_ r: Result) -> AsyncThrows { .join(.try_(r, .unit)) } // await ΩʔϫʔυΛࣗ࡞ func await_(_ a: Async) -> AsyncThrows { .join(.await_(a, .unit)) } /05& ͜ͷؔख͸͢Ͱʹ߹੒ࡁΈ͕ͩɺ ෼ղͯ͠߹੒ͤ͞Δ͜ͱ΋Մೳ ؔखϨϕϧͰ͸߹੒ՄೳͰɺ ϞφυϨϕϧͰ͸ग़དྷͳ͍ ݴޠ࢓༷ΩʔϫʔυΛ ࣗ࡞Ͱ͖Δʂ

Slide 48

Slide 48 text

ࣗ༝ϞφυʹΑΔܭࢉޮՌͷ߹੒ let monad: AsyncThrows = … AsyncThrows.do { monadResult <- await_(monad) monad_ <- try_(monadResult) is_ <- await_(monad_.is) just_ = await_(is_.just) a_ <- try_(just_.a) monoid_ <- await_(a_.monoid) return monoid_ } ࣗ༝ϞφυΛ࢖ͬͯ ݴޠ಺ʹಠࣗͷ%4-Λߏங ˣ USZBXBJU྆ํΛؚΜͩ ݴޠ࢓༷ͷॻ͖ํͱ ΄΅มΘΒͳ͍ॻ͖ຯʹͳΔ

Slide 49

Slide 49 text

let ast = AsyncThrows.do { /* લϖʔδ */ } Free.join(.await_(monad, { monadResult in Free.join(.try_(monadResult, { monad_ in Free.join(.await_(monad_.is, { is_ in Free.join(.await_(is_.just, { just_ in Free.join(.try_(just_.a, { a_ in Free.join(.await_(a_.monoid, { monoid_ in Free.unit(monoid_) })) })) })) })) })) })) ࣗ༝ϞφυʹΑͬͯɺ ݴޠ಺%4- ߏจ ΛߏஙͰ͖Δ ˠ͜ΕΛͲ͏lղऍz͢Δ͔͕࣍ͷ՝୊

Slide 51

Slide 51 text

·ͱΊʢϞφυʣ wϞφυNBQVOJUqBU.BQ Ϟφυଇ wϞφυEPه๏Λ࢖͏ͱɺखଓ͖ʹมߋͰ͖Δ wࣗ༝ϞφυΛ࢖͏ͱɺUSZBXBJUͷ߹੒͕ࣗ࡞Ͱ͖Δ wϞφυͱݴޠ࢓༷ʢखଓ͖ʷΩʔϫʔυʣ͸౳ՁͱΈͳͤ Δ wܭࢉޮՌʹϞφυʹݴޠ࢓༷Ωʔϫʔυ

Slide 52

Slide 52 text

ܧଓ Continuation ! a POWER

Slide 53

Slide 53 text

ܧଓ $POUJOVBUJPO ͱ͸ʁ wܧଓίʔϧόοΫؔ਺ɿܕ"3 wܧଓ౉͠ελΠϧ $14 ɿܕ "3 3 // ࠶ܝɿൃද๯಄ͷؔ਺ // fetch: Request -> (Result -> Void) -> Void func fetch( request: Request, completion: @escaping (Result) -> Void ) -> Void ܧଓ $14 $POUJOVBUJPO1BTTJOH4UZMF ࢒ΓͷܭࢉʢίʔϧόοΫʣͷ͜ͱ ίʔϧόοΫ͕Ҿ਺ͷؔ਺

Slide 54

Slide 54 text

ྫɿ4XJGU6OTBGF$POUJOVBUJPO // stdlib/public/Concurrency/PartialAsyncTask.swift // NOTE: Result Λແࢹͨ͠όʔδϣϯ // typealias UnsafeContinuation = T -> Void struct UnsafeContinuation { func resume(with value: T) } // withUnsafeContinuation: ((T -> Void) -> Void) -> Async func withUnsafeContinuation( _ fn: (UnsafeContinuation) -> Void ) async -> T { ... } $14 $14͔Β"TZODؔ਺΁

Slide 55

Slide 55 text

௨ৗͷؔ਺ɿ௚઀ελΠϧ EJSFDUTUZMF // खଓ͖ (Ҿ਺ܕ͔ΒฦΓܕ΁ͷ direct style ͳؔ਺) let f: A -> B = ... let g: B -> C = ... let h: C -> D = ... func foo(a: A) -> D { let b = f(a) let c = g(b) let d = h(c) return d } // foo(a) == h(g(f(a)))

Slide 56

Slide 56 text

ܧଓ౉͠ελΠϧ $14 // खଓ͖Λʮܧଓ౉͠ελΠϧʯʹม׵ func fooCPS(a: A, completion: D -> R) -> R { return fCPS(a, { b in return gCPS(b, { c in return hCPS(c, { d in return completion(d) }) }) }) } $14 ௚઀ελΠϧͷίʔυͱ ಉ౳ͱΈͳͤΔ

Slide 57

Slide 57 text

ܧଓ౉͠ελΠϧ $14 // ैདྷͷҾ਺ͱ completion Ҿ਺ͷॱংΛೖΕସ͑Δ + ΧϦʔԽ func fooCPS(completion: D -> R) -> A -> R { return { a in return fCPS({ b in return gCPS({ c in return hCPS({ d in return completion(d) })(c) })(b) })(a) } } // fooCPS(completion) == fCPS(gCPS(hCPS(completion))) /05&͜ͷܗ΋ "%ʹର͢Δ$14

Slide 58

Slide 58 text

// CPSม׵ ʹ ถాͷิ୊͔ΒಘΒΕΔʮถాຒΊࠐΈʯ // cf. iOSDC 2018 ݍ࿦ͱSwift΁ͷԠ༻ p.60 func cpsTransform(_ xToY: X -> Y) -> (Y -> R) -> (X -> R) { return { yToR in return { x in yToR(xToY(x)) } } } let f: A -> B = ... let fCPS: (B -> R) -> (A -> R) = cpsTransform(f) let g: B -> C = ... let gCPS: (C -> R) -> (B -> R) = cpsTransform(g) let h: C -> D = ... let hCPS: (D -> R) -> (C -> R) = cpsTransform(h) let foo: A -> D = { a in h(g(f(a))) } let fooCPS: (D -> R) -> (A -> R) = { k in fCPS(gCPS(hCPS(k))) } $14ม׵ʹΑΓ ຤ඌ࠶ؼ࠷దԽͳͲ͕ߦ͑Δ

Slide 59

Slide 59 text

Slide 60

Slide 60 text

// खଓ͖Λʮܧଓ౉͠ελΠϧʯʹม׵ func fooCPS(a: A, completion: D -> R) -> R { return fCPS(a, { b in return gCPS(b, { c in return hCPS(c, { d in return completion(d) }) }) }) } ܧଓ౉͠ελΠϧʹΑΔܧଓͷٯ޲͖߹੒ GPP$14ͷ ܧଓ

Slide 61

Slide 61 text

// खଓ͖Λʮܧଓ౉͠ελΠϧʯʹม׵ func fooCPS(a: A, completion: D -> R) -> R { return fCPS(a, { b in return gCPS(b, { c in return hCPS(c, { d in return completion(d) }) }) }) } ܧଓ౉͠ελΠϧʹΑΔܧଓͷٯ޲͖߹੒ I$14ͷ ܧଓ

Slide 62

Slide 62 text

// खଓ͖Λʮܧଓ౉͠ελΠϧʯʹม׵ func fooCPS(a: A, completion: D -> R) -> R { return fCPS(a, { b in return gCPS(b, { c in return hCPS(c, { d in return completion(d) }) }) }) } ܧଓ౉͠ελΠϧʹΑΔܧଓͷٯ޲͖߹੒ H$14ͷ ܧଓ

Slide 63

Slide 63 text

// खଓ͖Λʮܧଓ౉͠ελΠϧʯʹม׵ func fooCPS(a: A, completion: D -> R) -> R { return fCPS(a, { b in return gCPS(b, { c in return hCPS(c, { d in return completion(d) }) }) }) } ܧଓ౉͠ελΠϧʹΑΔܧଓͷٯ޲͖߹੒ G$14ͷ ܧଓ

Slide 64

Slide 64 text

$14ͷ߹੒͸ܧଓΛ Լ͔Β্ʹ޲͔ͬͯ߹੒͢Δ

Slide 65

Slide 65 text

Slide 66

Slide 66 text

ܧଓϞφυͷEPه๏≅௨ৗͷίʔυ // CPS Λdoه๏Ͱखଓ͖Խ Cont.do { monad_ <- monad is_ <- monad_.is just_ <- is_.just a_ <- just_.a monoid_ <- a_.monoid return monoid_ } // ௚઀ελΠϧ func procedure() -> Bar { let monad_ = monad let is_ = monad_.is let just_ = is_.just let a_ = just_.a let monoid_ = a_.monoid return monoid_ } ≅ reflect reify

Slide 67

Slide 67 text

// CPS Λdoه๏Ͱखଓ͖Խ Cont.do { monad_ <- monad is_ <- monad_.is just_ <- is_.just a_ <- just_.a monoid_ <- a_.monoid return monoid_ } // ௚઀ελΠϧ func procedure() -> Bar { let monad_ = monad let is_ = monad_.is let just_ = is_.just let a_ = just_.a let monoid_ = a_.monoid return monoid_ } ≅ reflect reify ܧଓϞφυͷEPه๏≅௨ৗͷίʔυ

Slide 68

Slide 68 text

// CPS Λdoه๏Ͱखଓ͖Խ Cont.do { monad_ <- monad is_ <- monad_.is just_ <- is_.just a_ <- just_.a monoid_ <- a_.monoid return monoid_ } // ௚઀ελΠϧ func procedure() -> Bar { let monad_ = monad let is_ = monad_.is let just_ = is_.just let a_ = just_.a let monoid_ = a_.monoid return monoid_ } ≅ reflect reify ܧଓϞφυͷEPه๏≅௨ৗͷίʔυ

Slide 69

Slide 69 text

// CPS Λdoه๏Ͱखଓ͖Խ Cont.do { monad_ <- monad is_ <- monad_.is just_ <- is_.just a_ <- just_.a monoid_ <- a_.monoid return monoid_ } // ௚઀ελΠϧ func procedure() -> Bar { let monad_ = monad let is_ = monad_.is let just_ = is_.just let a_ = just_.a let monoid_ = a_.monoid return monoid_ } ≅ reflect reify ܧଓϞφυͷEPه๏≅௨ৗͷίʔυ

Slide 70

Slide 70 text

// CPS Λdoه๏Ͱखଓ͖Խ Cont.do { monad_ <- monad is_ <- monad_.is just_ <- is_.just a_ <- just_.a monoid_ <- a_.monoid return monoid_ } // ௚઀ελΠϧ func procedure() -> Bar { let monad_ = monad let is_ = monad_.is let just_ = is_.just let a_ = just_.a let monoid_ = a_.monoid return monoid_ } ≅ reflect reify ܧଓϞφυͷEPه๏≅௨ৗͷίʔυ

Slide 71

Slide 71 text

// CPS Λdoه๏Ͱखଓ͖Խ Cont.do { monad_ <- monad is_ <- monad_.is just_ <- is_.just a_ <- just_.a monoid_ <- a_.monoid return monoid_ } // ௚઀ελΠϧ func procedure() -> Bar { let monad_ = monad let is_ = monad_.is let just_ = is_.just let a_ = just_.a let monoid_ = a_.monoid return monoid_ } ≅ reflect reify ܧଓϞφυͷEPه๏≅௨ৗͷίʔυ

Slide 73

Slide 73 text

Structured Concurrency

Slide 74

Slide 74 text

ैདྷ (SBOE$FOUSBM%JTQBUDI ͷඇಉظॲཧ Dispatch Queue 0 (Thread 0) queue1 queue1.async queue2 queue2.async RVFVF͕ఀࢭͯ͠΋ RVFVF͕ಈ࡞͠ଓ͚Δ ਌ࢠ ೖΕࢠ ؔ܎ʹͳ͘ɺ ඇಉظHPUP͍ͯ͠ΔΑ͏ͳ΋ͷ

Slide 75

Slide 75 text

4USVDUVSFE$PODVSSFODZʹΑΔඇಉظॲཧ task0 task1 task0.addTask task2 task1.addTask UBTL͕ఀࢭ͢Δ·Ͱ UBTL͕ಈ࡞͠ଓ͚Δ ਌ࢠ ೖΕࢠ ؔ܎ɺ ίϧʔνϯ΍Ωϟϯηϧͷ ఻ൖ͕Մೳ

Slide 76

Slide 76 text

ܧଓʹΑΔϦιʔε؅ཧ // Ϧιʔεͷ֬อͱղ์Λߦ͏ɻ`bracket` ؔ਺ͱ΋ݴ͏ɻ // IO ͸෭࡞༻ʢPromise/Observable ͷΑ͏ͳ΋ͷʣ func retainRelease(retain value: IO, release: A -> IO) -> Cont, A> { Cont { k in value.flatMap { a in k(a).flatMapError { _ in release(a) } .flatMap { r in release(a).map { _ in r } } } } }

Slide 77

Slide 77 text

// Ϧιʔε؅ཧͷྫɿෳ਺ϑΝΠϧૢ࡞ func openFile(_ filename: String) -> IO { ... } let value = retainRelease( retain: openFile("1.txt"), release: { $0.closeFile() } ).run { handle1 in // ಡΈऔΓॲཧ ... retainRelease( retain: openFile("2.txt"), release: { $0.closeFile() } ).run { handle2 in // ॻ͖ࠐΈॲཧ ... } // είʔϓΛൈ͚Δͱ handle2.closeFile() } // είʔϓΛൈ͚Δͱ handle1.closeFile() IBOEMFͷ ੜଘظؒ͸ ඞͣIBOEMFͷ ੜଘظؒ಺ʹऩ·Δ IBOEMFͷ ੜଘظؒ IBOEMFͷ ੜଘظؒ

Slide 78

Slide 78 text

// Swift Structured Concurrency // (ඇಉظॲཧͷೖΕࢠߏ଄ɺCancellation ͷ఻ൖ) let asyncValues = retainRelease( // withTaskGroup retain: makeTaskGroup(), release: { $0.cancelAll() } ).run { taskGroup in for i in 0 ..< 10 { taskGroup.addTask( retainRelease( // withTaskCancellationHandler retain: makeTask(i), release: { $0.cancel() } ) ) } var values = [] for await value in taskGroup { // ݸʑͷ Task ׬ྃ & release values += [value] } return values } // είʔϓΛൈ͚Δͱ TaskGroup release ֤5BTLͷ ੜଘظؒ 5BTL(SPVQͷ ੜଘظؒ

Slide 79

Slide 79 text

CallCC Ca%-wi&-current-continuation

Slide 81

Slide 81 text

DBMM$$Λ࢖ͬͨܭࢉޮՌ SFUVSOCSFBLHVBSE // Early exit Cont.do { print("1") value <- callCC { exit in Cont.do { print("2") exit("3 (done)") // return / break / guard print("͜͜͸ݺ͹Εͳ͍") } } print(value) }

Slide 82

Slide 82 text

DBMM$$Λ࢖ͬͨܭࢉޮՌ EFGFS // Deferred call Cont.do { print("1") k <- callCC { exit in Cont.do { print("2") exit({ _ in print("4 (deferred done)") }) } } print("3") k() }

Slide 83

Slide 83 text

DBMM$$Λ࢖ͬͨܭࢉޮՌ ΤϥʔϋϯυϦϯά // Error handling let value: Double? = Cont.do { let x: Double = 1 let y: Double = 0 // or non-zero callCC { exitOK in Cont.do { error <- callCC { exitError in Cont.do { return y == 0 ? exitError("Can't be divided by 0") : exitOK(x / y) } } print(error) // Τϥʔ͕ى͖ͨ৔߹ͷΈ௨Δ return nil }} }

Slide 84

Slide 84 text

༨ஊɿTIJGUSFTFU ݶఆܧଓ wDBMM$$͸ʮϓϩάϥϜͷ࢒ΓͷܭࢉશͯʯΛଋറ͢ΔͷͰɺѻ͍͕େมةݥ wTIJGUSFTFU ݶఆܧଓ Λ࢖͏ͱɺଋറ͢ΔܧଓͷൣғΛݶఆతʹͰ͖Δ wʮDBMM$$ʯʴʮՄมࢀরʯʹݶఆܧଓʹϞφυͱಉ౳ͷܭࢉޮՌ func reset(_ m: Cont) -> Cont { Cont { k in k(m.run { $0 }) } } func shift(_ f: (A -> R) -> Cont) -> Cont { Cont { k in f(k).run { $0 } } }

Slide 85

Slide 85 text

༨ஊɿTIJGUSFTFUͷྫ let value = Cont.do { x <- reset(Cont.do { y <- shift { k in Cont.do { // k = { $0 + 3 } z <- k(10) return k(z) // k Λෳ਺ճ࣮ߦ͢Δ͜ͱ΋Մೳ }} return y + 3 // ޙଓͷ͜ͷίʔυ͕ k ʹଋറ͞ΕΔ }) return x - 1 // reset ͷ֎ͳͷͰ k ʹଋറ͞Εͳ͍ } // value = ((10 + 3) + 3) - 1 = 15

Slide 86

Slide 86 text

·ͱΊʢܧଓͱ$14ʣ wܧଓίʔϧόοΫʹ࢒Γͷܭࢉ w$14ܧଓ౉͠ελΠϧίʔϧόοΫ͕Ҿ਺ͷؔ਺ wܧଓͷྫɿύΠϓॲཧɺ4USVDUVSFE$PODVSSFODZ wDBMM$$ͱTIJGUSFTFUɿϞφυͱಉ౳ͷܭࢉޮՌ wϞφυΛ࢖Θͳͯ͘΋ɺܧଓΛ࢖ͬͯܭࢉޮՌΛߟ͑Δ͜ ͱ͕Ͱ͖Δ

Slide 87

Slide 87 text

ίϧʔνϯ Cooperative multitasking

Slide 88

Slide 88 text

ίϧʔνϯͱ͸ʁ func getVaccine1() { print("ϫΫ☆") // (1) pause() // தஅɿ੍ޚ͕ getVaccine2 ʹҠΔ print("νϯ☆") // (3) } func getVaccine2() { print("ϫΫ☆") // (2) pause() // தஅɿ੍ޚ͕ getVaccine1 ͷதஅϙΠϯτʹ໭Δ print("νϯ☆") // (4) } runCoroutines(getVaccine1, getVaccine2) // ϫΫνϯ2ճ઀छ // 1 → 2 → 3 → 4 ͷॱͰʢҎԼུʣ தஅɾ࠶։Ͱ͖ΔػೳΛ࣋ͭؔ਺ͷ͜ͱ ڠௐతϚϧνλεΫ

Slide 89

Slide 89 text

func getVaccine1() { print("ϫΫ☆") // (1) pause() // தஅɿ੍ޚ͕ getVaccine2 ʹҠΔ print("νϯ☆") // (3) } func getVaccine2() { print("ϫΫ☆") // (2) pause() // தஅɿ੍ޚ͕ getVaccine1 ͷதஅϙΠϯτʹ໭Δ print("νϯ☆") // (4) } runCoroutines(getVaccine1, getVaccine2) // ϫΫνϯ2ճ઀छ // 1 → 2 → 3 → 4 ͷॱͰʢҎԼུʣ ίϧʔνϯͱ͸ʁ

Slide 90

Slide 90 text

func getVaccine1() { print("ϫΫ☆") // (1) pause() // தஅɿ੍ޚ͕ getVaccine2 ʹҠΔ print("νϯ☆") // (3) } func getVaccine2() { print("ϫΫ☆") // (2) pause() // தஅɿ੍ޚ͕ getVaccine1 ͷதஅϙΠϯτʹ໭Δ print("νϯ☆") // (4) } runCoroutines(getVaccine1, getVaccine2) // ϫΫνϯ2ճ઀छ // 1 → 2 → 3 → 4 ͷॱͰʢҎԼུʣ ίϧʔνϯͱ͸ʁ

Slide 91

Slide 91 text

func getVaccine1() { print("ϫΫ☆") // (1) pause() // தஅɿ੍ޚ͕ getVaccine2 ʹҠΔ print("νϯ☆") // (3) } func getVaccine2() { print("ϫΫ☆") // (2) pause() // தஅɿ੍ޚ͕ getVaccine1 ͷதஅϙΠϯτʹ໭Δ print("νϯ☆") // (4) } runCoroutines(getVaccine1, getVaccine2) // ϫΫνϯ2ճ઀छ // 1 → 2 → 3 → 4 ͷॱͰʢҎԼུʣ ίϧʔνϯͱ͸ʁ

Slide 92

Slide 92 text

func getVaccine1() { print("ϫΫ☆") // (1) pause() // தஅɿ੍ޚ͕ getVaccine2 ʹҠΔ print("νϯ☆") // (3) } func getVaccine2() { print("ϫΫ☆") // (2) pause() // தஅɿ੍ޚ͕ getVaccine1 ͷதஅϙΠϯτʹ໭Δ print("νϯ☆") // (4) } runCoroutines(getVaccine1, getVaccine2) // ϫΫνϯ2ճ઀छ // 1 → 2 → 3 → 4 ͷॱͰʢҎԼུʣ ίϧʔνϯͱ͸ʁ

Slide 93

Slide 93 text

func getVaccine1() { print("ϫΫ☆") // (1) pause() // தஅɿ੍ޚ͕ getVaccine2 ʹҠΔ print("νϯ☆") // (3) } func getVaccine2() { print("ϫΫ☆") // (2) pause() // தஅɿ੍ޚ͕ getVaccine1 ͷதஅϙΠϯτʹ໭Δ print("νϯ☆") // (4) } runCoroutines(getVaccine1, getVaccine2) // ϫΫνϯ2ճ઀छ // 1 → 2 → 3 → 4 ͷॱͰʢҎԼུʣ ίϧʔνϯͱ͸ʁ

Slide 94

Slide 94 text

func getVaccine1() { print("ϫΫ☆") // (1) pause() // தஅɿ੍ޚ͕ getVaccine2 ʹҠΔ print("νϯ☆") // (3) } func getVaccine2() { print("ϫΫ☆") // (2) pause() // தஅɿ੍ޚ͕ getVaccine1 ͷதஅϙΠϯτʹ໭Δ print("νϯ☆") // (4) } runCoroutines(getVaccine1, getVaccine2) // ϫΫνϯ2ճ઀छ // 1 → 2 → 3 → 4 ͷॱͰʢҎԼུʣ ίϧʔνϯͱ͸ʁ

Slide 95

Slide 95 text

func receiver() { // தஅɿ receive Ͱ੍ޚ͕தஅ͠ɺsender ʹҠΔ // ࠶։ɿ money Λड͚औͬͯ࣍ͷߦ΁ money /* (4) */ <- receive() // (1) accountA += money // (5) } // (6) func sender() { accountB -= money // (2) // தஅɿ send Ͱ money ΛૹΓɺ੍ޚ͕ receiver ʹ໭Δ send(money) // (3) } // (7) runCoroutines(receiver, sender) // accountB͔Β͓͕ۚҾ͔Εɺૹۚ͞ΕɺaccountAʹ͓͕ۚೖΔʢ͜ͷؒʹׂΓࠐΈ͕ൃੜ͠ͳ͍ʣ ίϧʔνϯͷྫɿσʔλͷड͚౉͠ ʲڠௐతϚϧνλεΫʳ ҟͳΔλεΫ͕ಉ͡εϨουͰ ަޓʹߦΘΕΔͷͰ σʔλڝ߹ʹͳΒͳ͍

Slide 96

Slide 96 text

func receiver() { // தஅɿ receive Ͱ੍ޚ͕தஅ͠ɺsender ʹҠΔ // ࠶։ɿ money Λड͚औͬͯ࣍ͷߦ΁ money /* (4) */ <- receive() // (1) accountA += money // (5) } // (6) func sender() { accountB -= money // (2) // தஅɿ send Ͱ money ΛૹΓɺ੍ޚ͕ receiver ʹ໭Δ send(money) // (3) } // (7) runCoroutines(receiver, sender) // accountB͔Β͓͕ۚҾ͔Εɺૹۚ͞ΕɺaccountAʹ͓͕ۚೖΔʢ͜ͷؒʹׂΓࠐΈ͕ൃੜ͠ͳ͍ʣ ίϧʔνϯͷྫɿσʔλͷड͚౉͠

Slide 97

Slide 97 text

func receiver() { // தஅɿ receive Ͱ੍ޚ͕தஅ͠ɺsender ʹҠΔ // ࠶։ɿ money Λड͚औͬͯ࣍ͷߦ΁ money /* (4) */ <- receive() // (1) accountA += money // (5) } // (6) func sender() { accountB -= money // (2) // தஅɿ send Ͱ money ΛૹΓɺ੍ޚ͕ receiver ʹ໭Δ send(money) // (3) } // (7) runCoroutines(receiver, sender) // accountB͔Β͓͕ۚҾ͔Εɺૹۚ͞ΕɺaccountAʹ͓͕ۚೖΔʢ͜ͷؒʹׂΓࠐΈ͕ൃੜ͠ͳ͍ʣ ίϧʔνϯͷྫɿσʔλͷड͚౉͠

Slide 98

Slide 98 text

func receiver() { // தஅɿ receive Ͱ੍ޚ͕தஅ͠ɺsender ʹҠΔ // ࠶։ɿ money Λड͚औͬͯ࣍ͷߦ΁ money /* (4) */ <- receive() // (1) accountA += money // (5) } // (6) func sender() { accountB -= money // (2) // தஅɿ send Ͱ money ΛૹΓɺ੍ޚ͕ receiver ʹ໭Δ send(money) // (3) } // (7) runCoroutines(receiver, sender) // accountB͔Β͓͕ۚҾ͔Εɺૹۚ͞ΕɺaccountAʹ͓͕ۚೖΔʢ͜ͷؒʹׂΓࠐΈ͕ൃੜ͠ͳ͍ʣ ίϧʔνϯͷྫɿσʔλͷड͚౉͠

Slide 99

Slide 99 text

func receiver() { // தஅɿ receive Ͱ੍ޚ͕தஅ͠ɺsender ʹҠΔ // ࠶։ɿ money Λड͚औͬͯ࣍ͷߦ΁ money /* (4) */ <- receive() // (1) accountA += money // (5) } // (6) func sender() { accountB -= money // (2) // தஅɿ send Ͱ money ΛૹΓɺ੍ޚ͕ receiver ʹ໭Δ send(money) // (3) } // (7) runCoroutines(receiver, sender) // accountB͔Β͓͕ۚҾ͔Εɺૹۚ͞ΕɺaccountAʹ͓͕ۚೖΔʢ͜ͷؒʹׂΓࠐΈ͕ൃੜ͠ͳ͍ʣ ίϧʔνϯͷྫɿσʔλͷड͚౉͠

Slide 100

Slide 100 text

func receiver() { // தஅɿ receive Ͱ੍ޚ͕தஅ͠ɺsender ʹҠΔ // ࠶։ɿ money Λड͚औͬͯ࣍ͷߦ΁ money /* (4) */ <- receive() // (1) accountA += money // (5) } // (6) func sender() { accountB -= money // (2) // தஅɿ send Ͱ money ΛૹΓɺ੍ޚ͕ receiver ʹ໭Δ send(money) // (3) } // (7) runCoroutines(receiver, sender) // accountB͔Β͓͕ۚҾ͔Εɺૹۚ͞ΕɺaccountAʹ͓͕ۚೖΔʢ͜ͷؒʹׂΓࠐΈ͕ൃੜ͠ͳ͍ʣ ίϧʔνϯͷྫɿσʔλͷड͚౉͠

Slide 101

Slide 101 text

func receiver() { // தஅɿ receive Ͱ੍ޚ͕தஅ͠ɺsender ʹҠΔ // ࠶։ɿ money Λड͚औͬͯ࣍ͷߦ΁ money /* (4) */ <- receive() // (1) accountA += money // (5) } // (6) func sender() { accountB -= money // (2) // தஅɿ send Ͱ money ΛૹΓɺ੍ޚ͕ receiver ʹ໭Δ send(money) // (3) } // (7) runCoroutines(receiver, sender) // accountB͔Β͓͕ۚҾ͔Εɺૹۚ͞ΕɺaccountAʹ͓͕ۚೖΔʢ͜ͷؒʹׂΓࠐΈ͕ൃੜ͠ͳ͍ʣ ίϧʔνϯͷྫɿσʔλͷड͚౉͠

Slide 102

Slide 102 text

func receiver() { // தஅɿ receive Ͱ੍ޚ͕தஅ͠ɺsender ʹҠΔ // ࠶։ɿ money Λड͚औͬͯ࣍ͷߦ΁ money /* (4) */ <- receive() // (1) accountA += money // (5) } // (6) func sender() { accountB -= money // (2) // தஅɿ send Ͱ money ΛૹΓɺ੍ޚ͕ receiver ʹ໭Δ send(money) // (3) } // (7) runCoroutines(receiver, sender) // accountB͔Β͓͕ۚҾ͔Εɺૹۚ͞ΕɺaccountAʹ͓͕ۚೖΔʢ͜ͷؒʹׂΓࠐΈ͕ൃੜ͠ͳ͍ʣ ίϧʔνϯͷྫɿσʔλͷड͚౉͠

Slide 103

Slide 103 text

ࣗ༝ϞφυΛ࢖ͬͨίϧʔνϯ /// ෭࡞༻ M Λ෇͚ͨࣗ༝Ϟφυͱಉ͡ߏ଄ struct Coroutine { let resume: M indirect enum State { case done(A) // AΛฦͯ͠ऴྃ͢ΔλεΫ case suspended(F>) // F ʹแ·Ε͍ͯΔɺதஅ͞ΕͨλεΫ } } extension Monad[Coroutine] where Functor[F], Monad[M] { func flatMap(_ f: A -> Coroutine) -> Coroutine { self.resume.flatMap { state in switch state { case let .done(a): return f(a).resume case let .suspended(fco): return M.unit(.suspended(fco.map { $0.flatMap(f) })) } } } } લճͷࣗ༝Ϟφυ'SFF' "ʹ ෭࡞༻.͕௥Ճ͞Εͨܗ ࣗ༝Ϟφυม׵ࢠ

Slide 104

Slide 104 text

ίϧʔνϯม׵ؔ਺ TVTQFOEMJGU /// F Ͱఆٛ͞ΕͨܭࢉޮՌͷϕʔεߏ଄Λ suspended ঢ়ଶͷίϧʔνϯʹม׵ func suspend(_ fco: F>) -> Coroutine where Functor[F], Monad[M] { Coroutine(M.unit(.suspended(fco))) } /// ෭࡞༻ M Λίϧʔνϯʹม׵ func lift(_ effect: M) -> Coroutine where Functor[F], Monad[M] { Coroutine(effect.map(.done)) }

Slide 105

Slide 105 text

1BVTFίϧʔνϯϞφυ // pauseԋࢉΛߏ੒͢Δϕʔεؔख struct PauseF { let next: Next } // Trampoline ͱ΋ݺ͹ΕΔ typealias Pause = Coroutine // NOTE: pauseॲཧʹ suspend ؔ਺͕࢖ΘΕΔ func pause() -> Pause where Monad[M] { suspend(PauseF(.unit(()))) }

Slide 106

Slide 106 text

1BVTFίϧʔνϯϞφυʹΑΔ࣮૷ let getVaccine = lift(print("ϫΫ☆")) .flatMap { pause() } .flatMap { lift(print(“νϯ☆")) } // ·ͨ͸ do ه๏Λ࢖ͬͯ let getVaccine = Pause.do { lift(print("ϫΫ☆")) pause() lift(print("νϯ☆")) } runCoroutines(getVaccine, getVaccine) ࠷ॳͷखଓ͖ͷྫͱ ΄΅ಉ͡ܗ

Slide 107

Slide 107 text

// ༨ஊɿrunCoroutines ͷத਎͸ʁ extension Applicative[Coroutine] where Functor[F], Monad[M] { static func zipWith(_ f: A -> B -> C) -> Coroutine -> Coroutine -> Coroutine { { coroutineA in { coroutineB in coroutineA.flatMap { a in coroutineB.flatMap { b in .unit(f(a)(b)) } } } } } } func runCoroutines(_ pauses: [Pause]) -> M<[A]> where Monad[M] { func run(_ pause: Pause) -> M where Monad[M] { pause.resume.flatMap { state in switch state in { case let .done(arr): return M.unit(arr) case let .suspended(fco): return run(fco.next) } } } let combined = pauses.reduce(Pause.unit([])) { acc, pause in Pause.zipWith({ [$0] + $1 })(pause)(acc) } return run(combined) } ഑ྻͷ[JQͱߟ͑ํ͸ಉ͡ ͭͷ$PSPVUJOFΛʮ$14ͷ഑ྻʯ ʹݟཱͯɺ$14ϖΞͷ഑ྻΛ࡞Δ ͜͜Ͱ͸͞ΒʹGͰϖΞΛ$ʹม׵͢Δ $14ϖΞͷ഑ྻΛ ʮڠௐతʯʹ࣮ߦ͢Δ

Slide 110

Slide 110 text

// Send-Receive ίϧʔνϯϞφυʹΑΔ࣮૷ let sender = Send.do { accountA -= money send(money) } let receiver = Receive.do { money <- receive() accountB += money } runCoroutines(sender, receiver) // ༨ஊɿrunCoroutine ͷத਎ (NOTE: fatalError Λ࢖Θͳ͍޻෉΋Ͱ͖Δ) func runCoroutines(sender: Send, receiver: Receive) -> M<(A, B)> where Monad[M] { sender.resume.flatMap { sent in receiver.resume.flatMap { received in switch (sent, received) { case let (.done(a), .done(b)): return .unit((a, b)) case let (.done(a), .suspended(fco)): fatalError("sender ended too soon") case let (.suspended(a, co), .done(b)): return runCoroutines(co, .unit(b)) case let (.suspended(a, co), .suspended(f)): return runCoroutines(co, f(a)) } } } }

Slide 111

Slide 111 text

࠶ܝɿ"TZOD5ISPXTࣗ༝Ϟφυ // try & await ੍ޚԋࢉࢠΛߏ੒͢Δϕʔεؔख enum AsyncThrowsF { case try_(Result, Value -> Next) case await_(Async, Value -> Next) } typealias AsyncThrows = Free func try_(_ r: Result) -> AsyncThrows { .join(.try_(r, .unit)) } func await_(_ a: Async) -> AsyncThrows { .join(.await_(a, .unit)) }

Slide 112

Slide 112 text

"TZOD$PSPVUJOF // awaitԋࢉͷΈΛߏ੒͢Δϕʔεؔख struct AsyncF { let await_: (Async, Value -> Next) } typealias AsyncCoroutine = Coroutine // NOTE: awaitॲཧʹ suspend ؔ਺͕࢖ΘΕΔ func await_(_ a: Async) -> AsyncCoroutine { suspend(AsyncF(a, .unit)) }

Slide 113

Slide 113 text

"TZOD$PSPVUJOF // t = 19 Ͱ྆ํͷ஋Λड͚औΔ (2ͭͷฒྻ async let + await ʹ૬౰) let asyncValues: Async<(C1, C2)> = runCoroutines( AsyncCoroutine.do { a1 <- await_(task1a(sleep: 2)) // (1) at t = 0 b1 <- await_(task1b(a1, sleep: 3)) // (4) at t = 2 c1 <- await_(task1c(b1, sleep: 8)) // (5) at t = 5 return c1 // (7) at t = 13 }, AsyncCoroutine.do { a2 <- await_(task2a(sleep: 1)) // (2) at t = 0 b2 <- await_(task2b(a2, sleep: 5)) // (3) at t = 1 c2 <- await_(task2c(b2, sleep: 13)) // (6) at t = 6 return c2 // (8) at t = 19 } ) BXBJU@ TVTQFOE ࣌ʹ੍ޚ͕SVO$PSPVUJOFTʹ໭Γɺ ඇಉظܭࢉΛεέδϡʔϦϯάίʔϧόοΫ ܧଓ Λอଘ ˠ׬ྃޙʹܧଓΛݺͼɺ੍ޚΛ໭͢ @$PODVSSFODZ಺෦࣮૷ /05&$PSPVUJOFϞφυ ࣗ༝Ϟφυ Λ࢖Θͣɺ ܧଓϞφυঢ়ଶϞφυͰදݱ͢Δํ๏΋͋Δ

Slide 114

Slide 114 text

·ͱΊʢίϧʔνϯʣ wίϧʔνϯதஅɾ࠶։Ͱ͖ΔػೳΛ࣋ͭؔ਺ wࣗ༝Ϟφυม׵ࢠΛ࢖ͬͯίϧʔνϯΛදݱͰ͖Δ wKPJO͕TVTQFOEػೳΛ࣋ͭ wBXBJUͷਖ਼ମ͸TVTQFOE w"TZODSVO$PSPVUJOFT͸@$PODVSSFODZϥϯλΠϜ಺ʹ࣮૷ w/05&ʮܧଓϞφυঢ়ଶϞφυʯʹΑΔɺܧଓͷώʔϓ্Ͱͷ؅ཧ ͷํ͕@$PODVSSFODZͷຊདྷͷ࣮૷ʹ͍͔ۙ΋ 88%$

Slide 115

Slide 115 text

BTZODBXBJUΛ஌ΔͨΊʹ͸ ίϧʔνϯ͕ඞཁ ίϧʔνϯΛ஌ΔͨΊʹ͸ Ϟφυͱܧଓͷཧղ͕ෆՄܽ Swift 5.5

Slide 116

Slide 116 text

୯ͳΔࣗݾؔखͷݍʹ͓͚Δ ϞϊΠυର৅ͩΑ ܧଓJTύϫʔ ڠௐతͳൃදΛ໨ࢦͯ͠ ͕Μ͹Γ·͢ Ϟφυ ܧଓ ίϧʔνϯ

Slide 117

Slide 117 text

"MHFCSBJD&⒎FDUTͳͲ ݶఆܧଓ ϞφυΛEJSFDUTUZMFʹ͢Δ &GGFDU )BOEMFST %FMJNJUFE $POUJOVBUJPO .POBEJD 3FqFDUJPO

Slide 118

Slide 118 text

ࢀߟจݙ BQQMFTXJGU 4XJGU$PNNVOJUZ • SE-0296 Async/await • SE-0300 Continuations for interfacing async tasks with synchronous code • SE-0304 Structured concurrency • SE-0317 async let bindings • Swift concurrency: Behind the scenes - WWDC21 • Explore structured concurrency in Swift - WWDC21 • Meet async/await in Swift - WWDC21 • Coroutines in LLVM • Zewo/Venice • belozierov/SwiftCoroutine • Swift Language Updates - Learn Languages 2021

Slide 119

Slide 119 text

ࢀߟจݙ Ϟφυ • ശͰߟ͑ΔFunctorɺApplicativeͦͯ͠Monad - Qiita • Functor, Applicative, Monad | haskell • Free Monad | haskell • A Neighborhood of Infinity: The Mother of all Monads • The Comonad.Reader » Free Monads for Less (Part 1 of 3): Codensity • Eugenio Moggi. 1991. Notions of computation and monads • Philip Wadler. 1994. Monads and composable continuations • Philip Wadler. 1995. Monads for functional programming • Gordon Plotkin and John Power. 2002. Notions of Computation Determine Monads • W Swierstra. 2008. Data types a la carte. • Janis Voigtländer. 2008. Asymptotic Improvement of Computations over Free Monads • O Kiselyov, A Sabry, C Swords. 2013. Extensible effects: an alternative to monad transformers • E Rivas and M Jaskelioff. 2017. Notions of computation as monoids.

Slide 120

Slide 120 text

ࢀߟจݙ ܧଓɺ$14 • Haskell/Continuation passing style - Wikibooks, open books for an open world • continuation-passing style in nLab • ܧଓ | haskell • ܧଓ౉͠ͳHaskellϥΠϑ - ϞφυͱΘͨ͠ ͱίϞφυ • ܧଓϞφυʹΑΔϦιʔε؅ཧ - Qiita • Scala ʹ͓͚ΔܧଓϞφυͷ࣮૷ͱ׆༻ - Speaker Deck • Deep Dive async/await in Unity with UniTask(UniRx.Async) • ฒߦϓϩάϥϛϯάͱܧଓϞφυ • ઙҪ ݈Ұ. shift/reset ϓϩάϥϛϯάೖ໳ • Kenichi Asai. 2009. On typing delimited continuations: three new solutions to the printf problem • Continuations and Delimited Control • The Monad.Reader/Issue2/ FunWithLinearImplicitParameters

Slide 121

Slide 121 text

ࢀߟจݙ 4USVDUVSFE$PODVSSFODZ • 250bpm: Structured Concurrency • Notes on structured concurrency, or: Go statement considered harmful — njs blog • Structured concurrency | by Roman Elizarov | Medium • Roman Elizarov — Structured concurrency - YouTube

Slide 122

Slide 122 text

ࢀߟจݙ ίϧʔνϯ • Mario Blazevic. 2011. Coroutine Pipelines. The Monad.Reader Issue 19 • CoroutineϞφυͱεςʔτϚγϯ - The curse of λ • stackfulness of coroutines - lilyum ensemble • Introduction to the C++ coroutines | C++ - don't panic! • 20෼͘Β͍ͰΘ͔ͬͨؾ෼ʹͳΕΔC++20ίϧʔ νϯ • Coroutines guide | Kotlin • 2016 LLVM Developers’ Meeting: G. Nishanov “LLVM Coroutines” - YouTube • 2018 LLVM Developers’ Meeting: J. McCall “Coroutine Representations and ABIs in LLVM” - YouTube • GeeCON 2019: Dmitry Kandalov - Coroutines explained by example - YouTube • Functorial Blog - Stackless Coroutines in PureScript • Functorial Blog - Extensible Coeffects • Roshan James and Amr Sabry. 2011. Yield: Mainstream Delimited Continuations • R. P. Pieters and T. Schrijvers. 2020. Faster Coroutine Pipelines: A Reconstruction

Slide 123

Slide 123 text

ࢀߟจݙ "EWBODFEUPQJDT • Andrzej Filinski. 1989. Declarative Continuations and Categorical Duality • O Danvy, A Filinski. 1992. Representing control: A study of the CPS transformation • Andrzej Filinski. 1994. Representing Monads. • Andrzej Filinski. 1999. Representing layered monads. • Carl Bruggeman et al. 1996. Representing control in the presence of one-shot continuations • Gordon Plotkin and Matija Pretnar. 2009. Handlers of algebraic effects. • Matija Pretnar. 2015. An Introduction to Algebraic Effects and Handlers • yallop/effects-bibliography • S. Kawahara, et al. 2020. One-shot Algebraic Effects as Coroutines • ܧଓͱ͔ͷ࿩୊αʔϕΠ | κeenͷHappy Hacκing Blog • Ploeg & Kiselyov. 2014. Reflection without Remorse • Monadic Reflection in Haskell • ϞφυΛͭ͘Ζ͏ • Monadic Reflectionʹ͍ͭͯ - Arantium Maestum • Y. Forster, et al. 2017. On the Expressive Power of User- Defined Effects Effect Handlers, Monadic Reflection, Delimited Control. • Toru Kawata. 2018. A Contextual Reconstruction of Monadic Reflection.

Slide 124

Slide 124 text

Thanks! Yasuhiro Inami @inamiy