Upgrade to Pro — share decks privately, control downloads, hide ads and more …

圏論とSwiftへの応用 / iOSDC Japan 2018

Yasuhiro Inami
September 02, 2018

圏論とSwiftへの応用 / iOSDC Japan 2018

iOSDC Japan 2018 (Sep 2, 2018)

https://iosdc.jp/2018/
https://fortee.jp/iosdc-japan-2018/proposal/45b858e0-753c-4387-9210-5837cff6da7a

iOSDC Japan 2018 「圏論とSwiftへの応用」発表スライドメモ - Qiita
https://qiita.com/inamiy/items/3e0c10d5eaf234b41c3d

iOSDC Japan 2018 で発表した「圏論とSwiftへの応用」の補足 - Qiita
https://qiita.com/inamiy/items/c4e85f22273e98b8db26

エラッタ:
p60. https://twitter.com/inamiy/status/1413894710372888577

Yasuhiro Inami

September 02, 2018
Tweet

More Decks by Yasuhiro Inami

Other Decks in Programming

Transcript

  1. ݍ࿦ͱɹɹɹ
    Swift΁ͷԠ༻
    2018/09/02 iOSDC 2018
    Yasuhiro Inami / @inamiy

    View full-size slide

  2. ݍ࿦
    Category Theory

    View full-size slide

  3. ݍ࿦ͱ͸ʁ
    • ʮ఺ʯͱʮ໼ҹʯΛ࢖ͬͨ਺ֶͷ Foundation.framework
    • ఺ΑΓ΋໼ҹͷํ͕ॏཁʢू߹࿦ͷߟ͑ํͱ͸ٯʣ
    • Ԡ༻ൣғ͕޿͍ɿ ਺ֶɺ࿦ཧֶɺܭࢉػՊֶɺཧ࿦෺ཧֶɺ
    ೝ஌Պֶɺ఩ֶɺੜ෺ֶɺetc
    • ਺ֶͷ஌͕ࣝθϩͰ΋ֶ΂Δʢඍੵɺઢܗ୅਺΋͍Βͳ͍ʣ
    • ؔ਺ܕϓϩάϥϛϯάͰେ׆༂

    View full-size slide

  4. ݍ࿦ΛֶͿ → ܕγεςϜ νϣοτσΩϧ
    • ࠶ؼܕʢෆಈ఺ɺfixɺreduce (fold) / sequence (unfold)ʣ
    • શশྔԽ ʢύϥϝʔλଟ૬ɺδΣωϦΫεʣ
    • ଘࡏྔԽ ʢϓϩτίϧ (existential container)ʣ
    • ߴϥϯΫଟ૬ʢଟ૬ؔ਺ΛҾ਺ͱͯ͠࢖͑Δʣ
    • ߴΧΠϯυଟ૬ʢܕίϯετϥΫλΛܕҾ਺ͱͯ͠࢖͑Δʣ
    • ґଘܕʢ஋ʹґଘ͢Δܕ͕࡞ΕΔʣ

    View full-size slide

  5. ݍ࿦ΛֶͿ

    ʮܕʯΛ
    ΑΓਂ͘ཧղͰ͖Δ

    Swiftͷݱঢ়ͱ
    ະདྷ͕ݟ͑ͯ͘Δ

    View full-size slide

  6. ※ ͓அΓ
    ͜ͷεϥΠυͰ͸ɺ
    ʮٙࣅSwiftʯΛ࢖ͬͯղઆ͍ͯ͠·͢ɻ
    ( Swift 4.2ݱࡏɺݴޠػೳ͕଍Γͳ͍ͨΊ)

    View full-size slide

  7. ݍͷఆٛ
    Definition

    View full-size slide

  8. ݍͷఆٛ
    • ର৅ (object)ɿ
    • ࣹ (morphism)ɿ
    • ߃౳ࣹ (identity)ɿ
    • ߹੒ (composition)ɿ
    • ݁߹཯ (associativity)ɿ
    • ࢝Ҭ (domain) / ऴҬ (codomain):

    View full-size slide

  9. Swift ͷྫ
    // ߃౳ࣹʢྫɿ `f ⚬ id == f`ɺ `id ⚬ f == f`ʣ
    func id(_ a: A) -> A {
    return a
    }
    // ؔ਺ͷ߹੒ʢྫɿ `(g ⚬ f)(x) == g(f(x))`ʣ
    func ⚬ (_ g: B -> C, _ f: A -> B) -> A -> C {
    return { g(f($0)) }
    }

    View full-size slide

  10. ؔख
    Functor

    View full-size slide

  11. ؔख (Functor)
    • ݍΛʮର৅ʯʹɺ ͋Δݍ͔Β͋Δݍ
    ΁ͷߏ଄ʢ໼ҹશମͷܗʣΛอͭ
    ʮࣹʯʢϚοϐϯάʣ
    • ֤ର৅ ʹ͍ͭͯ ʹରԠ
    • ֤ࣹ ʹ͍ͭͯ ʹରԠ
    • ߏ଄ʢ߹੒ͱ߃౳ࣹʣΛอଘ͢Δ


    View full-size slide

  12. // ٙࣅSwift
    protocol Functor[F] {
    // Note: `self.map { ... }` ʢΠϯελϯεϝιουʣ
    // ͱͯ͠΋࢖͑Δͱ͢Δ
    static func map(_ self: F, _ f: A -> B) -> F
    }
    extension Functor[Array] { ... }
    // ࢖༻ྫɿ Array ==> Array
    [1, 2, 3].map(String.init) == ["1", "2", "3"]

    View full-size slide

  13. ؔखͱ͸ʮmap ͕Ͱ͖Δʯ͜ͱ
    map = ίϯςφΛม͑ͣʹ
    த਎Λม͑Δʁ
    ʢର৅͕த৺ (pointwise) ͷߟ͑ํʣ

    View full-size slide

  14. // લܝ
    protocol Functor[F] {
    static func map(_ self: F, _ f: A -> B) -> F
    }
    // Ҿ਺ॱংΛೖΕସ͑ͯɺΧϦʔԽ͢Δͱɾɾɾ
    protocol Functor[F] {
    // ؔ਺্࣋ͪ͛ (lifting)
    static func map(_ f: A -> B) -> F -> F
    }
    map ͕ f: A -> B ͔Β F(f): F -> F ΁ͷม׵ʹͳΔ

    View full-size slide

  15. map ʢؔखʣ͸ɾɾɾ
    ݍͷؔ਺ f Λɺผͷݍͷؔ਺
    F(f) = map(f) ʹࣸ͢
    ʢࣹ͕த৺ (pointfree) ͷߟ͑ํʣ

    View full-size slide

  16. ͷҙຯ
    2ͭͷࣹ ʹ͍ͭͯɺઌʹ߹੒͔ͯ͠Β Λద༻ͯ͠΋ɺ
    ΛͦΕͧΕʹద༻͔ͯ͠Β߹੒ͯ͠΋ಉ͡

    View full-size slide

  17. ͷྫ
    let count: String -> Int = { $0.count }
    let isEven: Int -> Bool = { $0 % 2 == 0 }
    ["Hello"].map(isEven ⚬ count) // ؔ਺߹੒ ʴ 1ճ `map`
    == ["Hello"].map(count).map(isEven) // 2ճ `map`
    // ==> F.map(isEven ⚬ count) == F.map(isEven) ⚬ F.map(count)
    !
    2ճ map͸ɺʮؔ਺߹੒ʴ1ճ mapʯͱಉ͡ʢܭࢉྔ࡟ݮʣ

    View full-size slide

  18. ༨ஊɿࣗݾؔख (Endofunctor)
    ͜͜·Ͱɺ Array ΍ Array Λɺ Int ΍ String
    ͱ͸ ผͷݍʢArray ͷݍʣ ͷର৅ͱͯ͠ߟ͖͑ͯͨ
    ɹɹɹɹɹɹɹɹɹɹɹɹɹˣ
    ࣮ࡍ͸ɺ͢΂ͯಉ͡SwiftͷܕͳͷͰɺ1ͭͷʮSwiftݍ ʯͷର৅
    ͱͯ͠ѻͬͯྑ͍
    ɹɹɹɹɹɹɹɹɹɹɹɹɹˣ
    ϓϩάϥϛϯάͷੈքͷ ؔख (Functor) ͱ͸ɺ࣮͸ ࣗݾؔख
    ʢݍ͔Βಉ͡ݍ΁ͷؔख ʹ ଟ૬ؔ਺ mapʣ ͷ͜ͱ

    View full-size slide

  19. ࣗવม׵
    Natural Transformation

    View full-size slide

  20. ࣗવม׵
    • 2ͭͷݍͷؒͷ"ࣹ"Ͱ͋ΔؔखΛʮର
    ৅ʯͱͯ͠ѻͬͨͱ͖ͷɺؔख͔Β
    ؔख΁ͷʮࣹʯ
    • ݍ ͱؔख ͕༩͑
    ΒΕͨͱ͖ɺࣗવม׵ ͸
    ͷࣹ ͷू߹
    Ͱɺ೚ҙͷ ʹରͯ͠ɺҎ
    Լͷ౳ࣜʢՄ׵ਤࣜʣ Λຬͨ͢ɿ

    View full-size slide

  21. ͷҙຯ
    // ࣗવม׵ʢத਎Λม͑ͣʹίϯςφΛม͑Δʮଟ૬ؔ਺ʯʣ
    func alpha(_ fa: F) -> G { ... }
    // Մ׵ࣜ
    alpha(fa.map(f)) == alpha(fa).map(f)
    // ==> alpha ⚬ F.map(f) == G.map(f) ⚬ alpha
    !
    F.map(f) Λઌʹܭࢉ͔ͯ͠Β alpha Λܭࢉͯ͠΋ɺalpha
    Λઌʹܭࢉ͔ͯ͠Β G.map(f) Ͱ΋ɺͲͪΒͰ΋੒Γཱͭ

    View full-size slide

  22. ͷྫ
    /// Array -> Optional ΁ͷࣗવม׵
    func arrFirst(_ arr: Array) -> Optional {
    return arr.first
    }
    arrFirst( [1, 2, 3].map(String.init) ) // `map` ͔ͯ͠Β `first`
    == arrFirst([1, 2, 3]).map(String.init) // `first` ͔ͯ͠Β `map`
    !
    ӈลͷํ͕ܭࢉྔ͕গͳ͍ → ίϯύΠϥ͕࠷దԽͰ͖Δ

    View full-size slide

  23. ถాͷิ୊
    Yoneda Lemma

    View full-size slide

  24. ถాͷิ୊

    View full-size slide

  25. ถాͷิ୊ ʹʮࣗવม׵ʯͱʮ஋ʯͷ1:1ରԠ
    let fa: F = ... // ஋
    func closure(_ f: A -> B) -> F { // ࣗવม׵
    return fa.map(f) // `fa` Λ಺෦Ͱ࣋ͭ
    }
    faʢ஋ʣͱ closureʢ஋Λดแͨ͠ଟ૬ؔ਺ʣ͸"ಉ͡΋ͷ"ɺ
    ͦΕΒͷܕ͸ ಉܕʢ૬ޓʹม׵Մೳʣ ͱΈͳͤΔ

    View full-size slide

  26. // F(A) ͔Β ∀B. (A -> B) -> F(B) ΁ͷม׵
    func faToClosure(_ fa: F) -> (A -> B) -> F {
    return { f in
    return fa.map(f)
    }
    }
    // ∀B. (A -> B) -> F(B) ͔Β F(A) ΁ͷม׵
    func closureToFa(
    _ closure: /* ϥϯΫ2ଟ૬ */ (A -> B) -> F
    ) -> F {
    return closure(id)
    }

    View full-size slide

  27. ࢀߟεϥΠυ2ɿ ಉܕͷ࿩
    2 https://speakerdeck.com/inamiy/algebraic-data-type-in-swift
    ༨ஊɿถాͷิ୊Λ࢖͏ͱ ͷࢦ਺๏ଇ΍ɺ෼഑๏ଇͳͲ͕؆୯ʹূ໌Ͱ͖·͢

    View full-size slide

  28. ถాͷิ୊͔Βɺܧଓ (CPS) ͱCPSม׵
    • ʢ߃౳ؔखʣͱ͓͘ͱɺCPSʢܧଓʣ
    • ͱ͓͘ͱɺCPSม׵ʢʹ ถాຒΊࠐΈ ʣ
    func cpsTransform(_ f: X -> A) -> (A -> B) -> (X -> B) {
    return { aToB in
    return { x in aToB(f(x)) }
    }
    }

    View full-size slide

  29. func fac(_ n: Int) -> Int {
    //

    ຤ඌ࠶ؼͷܗͰ͸ͳ͍ʢ͕ɺཪͰίϯύΠϥ͕࠷దԽͯ͘͠ΕΔʣ
    return n == 0 ? 1 : n * fac (n - 1)
    }
    // `cpsTransform` Λ࢖Θͣɺखॻ͖ͰܧଓʹΑΔ຤ඌ࠶ؼ
    func facCPS(_ n: Int, _ next: Int -> R) -> R {
    return n == 0 ? next(1) : facCPS(n - 1, { next(n * $0) })
    }
    // `cpsTransform` Λ࢖ͬͨ৔߹ʢ຤ඌ࠶ؼ࠷దԽʣ
    let facCPSAuto: (Int -> Int) -> Int -> Int = cpsTransform(fac)
    facCPS(4, id) // 24 ʢखಈͰ຤ඌ࠷దʣ
    facCPSAuto(id)(4) // 24 ʢࣗಈͰ຤ඌ࠷దʣ

    View full-size slide

  30. ਵ൐
    Adjunction

    View full-size slide

  31. ࣗ༝ؔख ๨٫ؔख

    View full-size slide

  32. // ٙࣅSwift
    protocol Adjunction[F, U] where Functor[F], Functor[U] {
    /// (F(C) -> D) -> (C -> U(D))
    static func leftAdjunct(_ f: F -> D)
    -> C -> U
    /// (C -> U(D)) -> (F(C) -> D)
    static func rightAdjunct(_ f: C -> U)
    -> F -> D
    }

    View full-size slide

  33. ਵ൐ͷྫ
    /// ੵͷܕʢλϓϧʣ
    typealias Tuple = (B, A) // ஫ҙɿ޲͖͕ٯ
    /// ؔ਺ͷܕʢReaderͱ΋ݺ͹ΕΔʣ
    typealias Func = A -> B

    View full-size slide

  34. extension Functor[Tuple] { // `Tuple` ͸ `A` ͷΈͷ෦෼ద༻
    static func map(_ f: C -> D) -> Tuple -> Tuple {
    return { t in
    return (f(t.0), t.1)
    }
    }
    }
    extension Functor[Func] {
    static func map(_ f: C -> D) -> Func -> Func {
    return { fun in
    return f ⚬ fun
    }
    }
    }

    View full-size slide

  35. // Tuple ⊣ Func
    extension Adjunction[Tuple, Func] {
    static func leftAdjunct(_ f: Tuple -> D)
    -> C -> Func {
    return { c in { a in f((c, a)) } }
    }
    static func rightAdjunct(_ f: C -> Func)
    -> Tuple -> D {
    return { t in f(t.0)(t.1) }
    }
    }

    View full-size slide

  36. func curry(_ f: (A, B) -> C) -> A -> B -> C {
    return { a in
    return { b in
    return f(a, b)
    }
    }
    }
    func uncurry(_ f: A -> B -> C) -> (A, B) -> C {
    return { a, b in
    return f(a)(b)
    }
    }

    View full-size slide

  37. leftAdjunct
    == curry
    rightAdjunct
    == uncurry
    (Tuple ⊣ Func ͷͱ͖)

    View full-size slide

  38. ਵ൐ͷผͷఆٛ

    View full-size slide

  39. extension Adjunction {
    static func unit(_ c: C) -> U> {
    // `leftAdjunct` ͷୈ1Ҿ਺͸ `F -> D` ͳͷͰɺ
    // `id` Λద༻͢Δͱɺܕͱͯ͠ `D = F` ͕֬ఆ͢Δ
    return leftAdjunct(id)(c)
    }
    static func counit(_ fud: F>) -> D {
    return rightAdjunct(id)(fud)
    }
    }

    View full-size slide

  40. counit: F> -> D ʹɺ D = F Λ୅ೖͯ͠ΈΔͱ
    counit: F>> -> F
    ͜ΕΛ͞Βʹ ؔख U ͰϦϑτ͢Δͱ
    U.map(counit): U>>> -> U>
    extension Adjunction {
    static func join(_ x: U>>>) -> U> {
    return map(counit)
    }
    }

    View full-size slide

  41. ੔ཧͯ͠ΈΔɿ
    extension Adjunction {
    static func unit(_ c: C) -> U> {
    return leftAdjunct(id)(c)
    }
    static func join(_ x: U>>>) -> U> {
    return map(counit)
    }
    }
    ͜͜Ͱɺ U> = M ͱஔ͍ͯΈΔͱɾɾɾ

    View full-size slide

  42. protocol Monad[M] where Functor[M] {
    static func unit(_ c: C) -> M
    static func join(_ mmc: M>) -> M
    }
    extension Monad {
    static func flatMap(_ f: C -> M)
    -> M -> M {
    return { (join ⚬ map(f))($0) }
    }
    }

    View full-size slide

  43. ਵ൐

    Ϟφυ

    View full-size slide

  44. ྫɿ Tuple ⊣ Func ΑΓɺ
    Func>
    ʹʮؔ਺ͷதʹλϓϧΛೖΕΔʯʹ ঢ়ଶϞφυ
    struct State {
    let runState: S -> (A, S)
    init(_ fun: Func>) {
    // `Func>` ͱ
    // `S -> (A, S)` ͸࣮͸ಉ͡ʂ
    self.runState = fun
    }
    }

    View full-size slide

  45. ͸Ϟφυ
    Ͱ͸ɺٯͷ ͸lĤĤĤ

    View full-size slide

  46. // W ͸ Ϟφυ M ͷٯ
    protocol Comonad[W] where Functor[W] {
    // Ϟφυͷ `unit: C -> M` ͷٯ
    static func counit(_ wc: W) -> D
    // Ϟφυͷ `join: M> -> M` ͷٯ
    static func duplicate(_ wc: W) -> W>
    }

    View full-size slide

  47. ༨Ϟφυ
    Comonad

    View full-size slide

  48. ਵ൐

    ༨Ϟφυ

    View full-size slide

  49. ྫɿ Tuple ⊣ Func ΑΓɺ
    Tuple>
    ʹʮλϓϧͷதʹؔ਺ΛೖΕΔʯʹ ༨ঢ়ଶ༨Ϟφυ
    struct Store { // CoState ͱ΋ݴΘΕΔ
    let setter: A -> S
    let getter: A
    init(_ t: Tuple>) {
    self.setter = t.0
    self.getter = t.1
    }
    }

    View full-size slide

  50. ͦͯ͠ɺ S -> Store ʢ༨୅਺ɺCoalgebraʣΛߟ͑Δ
    struct Lens {
    let setter: S -> A -> S
    let getter: S -> A
    init(_ f: S -> Store) {
    self.setter = { s in f(s).setter }
    self.getter = { s in f(s).getter }
    }
    }

    View full-size slide

  51. Ϩϯζ͸
    ༨ঢ়ଶ༨Ϟφυͷ
    ༨୅਺
    Lenses are Costate
    Comonad
    Coalgebras

    View full-size slide

  52. ·ͱΊ
    • ݍɺ߹੒ɺ߃౳ࣹ
    • ؔख (Functor) → ݍͷࣹΛɺผͷݍʹࣸ͢ (map)
    • ࣗવม׵ (Natural Transformation) → Մ׵ਤࣜɺଟ૬ؔ਺
    • ถాͷิ୊ (Yoneda Lemma) → ܧଓ (CPS) ͳͲ
    • ਵ൐ (Adjunction) → ΧϦʔԽɺϞφυɺ༨Ϟφυ
    • Ϟφυ / ༨Ϟφυ ((Co-)Monad) → ঢ়ଶϞφυɺϨϯζ

    View full-size slide

  53. ͞ΒʹֶͿͨΊʹ
    • ۃݶ (Limit) l ੵɺΠίϥΠβɺҾ͖໭͠ɺetc
    • Τϯυ / ༨Τϯυ (End / Coend)
    • ୅਺ / ༨୅਺ (Algebra / Coalgebra)
    • ࣗ༝ؔखɾࣗ༝Ϟφυ (Free Functor, Free Monad)
    • Χϯ֦ு (Kan Extension)
    • ϞϊΠυݍɾ๛য়ݍ (Monoidal / Enriched Category)

    View full-size slide

  54. ࢀߟจݙʢॳֶऀ޲͚ʣ
    • Bartosz Milewski's Programming Cafe | Category Theory,
    Haskell, Concurrency, C++

    !
    Bartosz Milewski - YouTube

    !
    TheCatsters - YouTube
    • Category theory for beginners
    • ݍ࿦ษڧձ @ ϫʔΫεΞϓϦέʔγϣϯζ

    View full-size slide

  55. ࢀߟจݙʢதʙ্ڃऀ޲͚ʣ

    !
    ݍ࿦ ݪஶୈ2൛ | Steve Awodey

    !
    ϕʔγοΫݍ࿦ ීวੑ͔Βͷ଎शίʔε | Tom Leinster

    !
    ݍ࿦ͷجૅ | Saunders MacLane
    • ݍ࿦ | ұେ੔Ҭ
    • ᐻࢁਖ਼޾ͷΩϚΠϥࣂҭه
    • nLab

    View full-size slide

  56. Thanks!
    Yasuhiro Inami
    @inamiy

    View full-size slide