Yasuhiro Inami
September 02, 2018
5.1k

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

iOSDC Japan 2018 (Sep 2, 2018)

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

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

Yasuhiro Inami

September 02, 2018

Transcript

2. None
3. None

5. None
6. ݍ࿦ͱ͸ʁ • ʮ఺ʯͱʮ໼ҹʯΛ࢖ͬͨ਺ֶͷ Foundation.framework • ఺ΑΓ΋໼ҹͷํ͕ॏཁʢू߹࿦ͷߟ͑ํͱ͸ٯʣ • Ԡ༻ൣғ͕޿͍ɿ ਺ֶɺ࿦ཧֶɺܭࢉػՊֶɺཧ࿦෺ཧֶɺ ೝ஌Պֶɺ఩ֶɺੜ෺ֶɺetc

• ਺ֶͷ஌͕ࣝθϩͰ΋ֶ΂Δʢඍੵɺઢܗ୅਺΋͍Βͳ͍ʣ • ؔ਺ܕϓϩάϥϛϯάͰେ׆༂
7. ݍ࿦ΛֶͿ → ܕγεςϜ νϣοτσΩϧ • ࠶ؼܕʢෆಈ఺ɺfixɺreduce (fold) / sequence (unfold)ʣ

• શশྔԽ ʢύϥϝʔλଟ૬ɺδΣωϦΫεʣ • ଘࡏྔԽ ʢϓϩτίϧ (existential container)ʣ • ߴϥϯΫଟ૬ʢଟ૬ؔ਺ΛҾ਺ͱͯ͠࢖͑Δʣ • ߴΧΠϯυଟ૬ʢܕίϯετϥΫλΛܕҾ਺ͱͯ͠࢖͑Δʣ • ґଘܕʢ஋ʹґଘ͢Δܕ͕࡞ΕΔʣ

11. None
12. None
13. None
14. None
15. None
16. None
17. None
18. None
19. None
20. None
21. ݍͷఆٛ • ର৅ (object)ɿ • ࣹ (morphism)ɿ • ߃౳ࣹ (identity)ɿ

• ߹੒ (composition)ɿ • ݁߹཯ (associativity)ɿ • ࢝Ҭ (domain) / ऴҬ (codomain):
22. Swift ͷྫ // ߃౳ࣹʢྫɿ `f ⚬ id == f`ɺ `id

⚬ f == f`ʣ func id<A>(_ a: A) -> A { return a } // ؔ਺ͷ߹੒ʢྫɿ `(g ⚬ f)(x) == g(f(x))`ʣ func ⚬ <A, B, C>(_ g: B -> C, _ f: A -> B) -> A -> C { return { g(f(\$0)) } }

24. None
25. None
26. None
27. None
28. None
29. None
30. None
31. ؔख (Functor) • ݍΛʮର৅ʯʹɺ ͋Δݍ͔Β͋Δݍ ΁ͷߏ଄ʢ໼ҹશମͷܗʣΛอͭ ʮࣹʯʢϚοϐϯάʣ • ֤ର৅ ʹ͍ͭͯ

ʹରԠ • ֤ࣹ ʹ͍ͭͯ ʹରԠ • ߏ଄ʢ߹੒ͱ߃౳ࣹʣΛอଘ͢Δ • •
32. // ٙࣅSwift protocol Functor[F] { // Note: `self.map { ...

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

34. // લܝ protocol Functor[F] { static func map<A, B>(_ self:

F<A>, _ f: A -> B) -> F<B> } // Ҿ਺ॱংΛೖΕସ͑ͯɺΧϦʔԽ͢Δͱɾɾɾ protocol Functor[F] { // ؔ਺্࣋ͪ͛ (lifting) static func map<B>(_ f: A -> B) -> F<A> -> F<B> } map ͕ f: A -> B ͔Β F(f): F<A> -> F<B> ΁ͷม׵ʹͳΔ
35. None
36. map ʢؔखʣ͸ɾɾɾ ݍͷؔ਺ f Λɺผͷݍͷؔ਺ F(f) = map(f) ʹࣸ͢ ʢࣹ͕த৺

(pointfree) ͷߟ͑ํʣ

38. ͷྫ 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ʯͱಉ͡ʢܭࢉྔ࡟ݮʣ
39. ༨ஊɿࣗݾؔख (Endofunctor) ͜͜·Ͱɺ Array<Int> ΍ Array<String> Λɺ Int ΍ String

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

42. None
43. None
44. None
45. ࣗવม׵ • 2ͭͷݍͷؒͷ"ࣹ"Ͱ͋ΔؔखΛʮର ৅ʯͱͯ͠ѻͬͨͱ͖ͷɺؔख͔Β ؔख΁ͷʮࣹʯ • ݍ ͱؔख ͕༩͑ ΒΕͨͱ͖ɺࣗવม׵

͸ ͷࣹ ͷू߹ Ͱɺ೚ҙͷ ʹରͯ͠ɺҎ Լͷ౳ࣜʢՄ׵ਤࣜʣ Λຬͨ͢ɿ
46. ͷҙຯ // ࣗવม׵ʢத਎Λม͑ͣʹίϯςφΛม͑Δʮଟ૬ؔ਺ʯʣ func alpha<A>(_ fa: F<A>) -> G<A> {

... } // Մ׵ࣜ alpha(fa.map(f)) == alpha(fa).map(f) // ==> alpha ⚬ F.map(f) == G.map(f) ⚬ alpha ! F.map(f) Λઌʹܭࢉ͔ͯ͠Β alpha Λܭࢉͯ͠΋ɺalpha Λઌʹܭࢉ͔ͯ͠Β G.map(f) Ͱ΋ɺͲͪΒͰ΋੒Γཱͭ
47. ͷྫ /// Array -> Optional ΁ͷࣗવม׵ func arrFirst<A>(_ arr: Array<A>)

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

49. None
50. None
51. None
52. None
53. None
54. None

56. ถాͷิ୊ ʹʮࣗવม׵ʯͱʮ஋ʯͷ1:1ରԠ let fa: F<A> = ... // ஋ func

closure<B>(_ f: A -> B) -> F<B> { // ࣗવม׵ return fa.map(f) // `fa` Λ಺෦Ͱ࣋ͭ } faʢ஋ʣͱ closureʢ஋Λดแͨ͠ଟ૬ؔ਺ʣ͸"ಉ͡΋ͷ"ɺ ͦΕΒͷܕ͸ ಉܕʢ૬ޓʹม׵Մೳʣ ͱΈͳͤΔ
57. // F(A) ͔Β ∀B. (A -> B) -> F(B) ΁ͷม׵

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

59. ถాͷิ୊͔Βɺܧଓ (CPS) ͱCPSม׵ • ʢ߃౳ؔखʣͱ͓͘ͱɺCPSʢܧଓʣ • ͱ͓͘ͱɺCPSม׵ʢʹ ถాຒΊࠐΈ ʣ func

cpsTransform<A, B, X>(_ f: X -> A) -> (A -> B) -> (X -> B) { return { aToB in return { x in aToB(f(x)) } } }
60. func fac(_ n: Int) -> Int { // ⚠ ຤ඌ࠶ؼͷܗͰ͸ͳ͍ʢ͕ɺཪͰίϯύΠϥ͕࠷దԽͯ͘͠ΕΔʣ

return n == 0 ? 1 : n * fac (n - 1) } // `cpsTransform` Λ࢖Θͣɺखॻ͖ͰܧଓʹΑΔ຤ඌ࠶ؼ func facCPS<R>(_ 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 ʢࣗಈͰ຤ඌ࠷దʣ

62. None
63. None
64. None

67. // ٙࣅSwift protocol Adjunction[F, U] where Functor[F], Functor[U] { ///

(F(C) -> D) -> (C -> U(D)) static func leftAdjunct<C, D>(_ f: F<C> -> D) -> C -> U<D> /// (C -> U(D)) -> (F(C) -> D) static func rightAdjunct<C, D>(_ f: C -> U<D>) -> F<C> -> D }
68. ਵ൐ͷྫ /// ੵͷܕʢλϓϧʣ typealias Tuple<A, B> = (B, A) //

஫ҙɿ޲͖͕ٯ /// ؔ਺ͷܕʢReaderͱ΋ݺ͹ΕΔʣ typealias Func<A, B> = A -> B
69. extension Functor[Tuple<A>] { // `Tuple<A>` ͸ `A` ͷΈͷ෦෼ద༻ static func

map(_ f: C -> D) -> Tuple<A, C> -> Tuple<A, D> { return { t in return (f(t.0), t.1) } } } extension Functor[Func<A>] { static func map(_ f: C -> D) -> Func<A, C> -> Func<A, D> { return { fun in return f ⚬ fun } } }
70. // Tuple<A> ⊣ Func<A> extension Adjunction[Tuple<A>, Func<A>] { static func

leftAdjunct<C, D>(_ f: Tuple<A, C> -> D) -> C -> Func<A, D> { return { c in { a in f((c, a)) } } } static func rightAdjunct<C, D>(_ f: C -> Func<A, D>) -> Tuple<A, C> -> D { return { t in f(t.0)(t.1) } } }
71. func curry<A, B, C>(_ f: (A, B) -> C) ->

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

74. None
75. None
76. None
77. None
78. None
79. None
80. extension Adjunction { static func unit<C>(_ c: C) -> U<F<C>>

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

F<U<F<C>>> -> F<C> ͜ΕΛ͞Βʹ ؔख U ͰϦϑτ͢Δͱ U.map(counit): U<F<U<F<C>>>> -> U<F<C>> extension Adjunction { static func join<C>(_ x: U<F<U<F<C>>>>) -> U<F<C>> { return map(counit) } }
82. ੔ཧͯ͠ΈΔɿ extension Adjunction { static func unit<C>(_ c: C) ->

U<F<C>> { return leftAdjunct(id)(c) } static func join<C>(_ x: U<F<U<F<C>>>>) -> U<F<C>> { return map(counit) } } ͜͜Ͱɺ U<F<C>> = M<C> ͱஔ͍ͯΈΔͱɾɾɾ
83. protocol Monad[M] where Functor[M] { static func unit<C>(_ c: C)

-> M<C> static func join<C>(_ mmc: M<M<C>>) -> M<C> } extension Monad { static func flatMap<C, C2>(_ f: C -> M<C2>) -> M<C> -> M<C2> { return { (join ⚬ map(f))(\$0) } } }

86. ྫɿ Tuple<S> ⊣ Func<S> ΑΓɺ Func<S, Tuple<S, A>> ʹʮؔ਺ͷதʹλϓϧΛೖΕΔʯʹ ঢ়ଶϞφυ

struct State<S, A> { let runState: S -> (A, S) init(_ fun: Func<S, Tuple<S, A>>) { // `Func<S, Tuple<S, A>>` ͱ // `S -> (A, S)` ͸࣮͸ಉ͡ʂ self.runState = fun } }

88. // W ͸ Ϟφυ M ͷٯ protocol Comonad[W] where Functor[W]

{ // Ϟφυͷ `unit: C -> M<C>` ͷٯ static func counit<D>(_ wc: W<D>) -> D // Ϟφυͷ `join: M<M<C>> -> M<C>` ͷٯ static func duplicate<D>(_ wc: W<D>) -> W<W<D>> }
89. None

92. ྫɿ Tuple<A> ⊣ Func<A> ΑΓɺ Tuple<A, Func<A, S>> ʹʮλϓϧͷதʹؔ਺ΛೖΕΔʯʹ ༨ঢ়ଶ༨Ϟφυ

struct Store<A, S> { // CoState ͱ΋ݴΘΕΔ let setter: A -> S let getter: A init(_ t: Tuple<A, Func<A, S>>) { self.setter = t.0 self.getter = t.1 } }
93. ͦͯ͠ɺ S -> Store<A, S> ʢ༨୅਺ɺCoalgebraʣΛߟ͑Δ struct Lens<A, S> {

let setter: S -> A -> S let getter: S -> A init(_ f: S -> Store<A, S>) { self.setter = { s in f(s).setter } self.getter = { s in f(s).getter } } }

95. ·ͱΊ • ݍɺ߹੒ɺ߃౳ࣹ • ؔख (Functor) → ݍͷࣹΛɺผͷݍʹࣸ͢ (map) •

ࣗવม׵ (Natural Transformation) → Մ׵ਤࣜɺଟ૬ؔ਺ • ถాͷิ୊ (Yoneda Lemma) → ܧଓ (CPS) ͳͲ • ਵ൐ (Adjunction) → ΧϦʔԽɺϞφυɺ༨Ϟφυ • Ϟφυ / ༨Ϟφυ ((Co-)Monad) → ঢ়ଶϞφυɺϨϯζ
96. ͞ΒʹֶͿͨΊʹ • ۃݶ (Limit) l ੵɺΠίϥΠβɺҾ͖໭͠ɺetc • Τϯυ / ༨Τϯυ

(End / Coend) • ୅਺ / ༨୅਺ (Algebra / Coalgebra) • ࣗ༝ؔखɾࣗ༝Ϟφυ (Free Functor, Free Monad) • Χϯ֦ு (Kan Extension) • ϞϊΠυݍɾ๛য়ݍ (Monoidal / Enriched Category)
97. ࢀߟจݙʢॳֶऀ޲͚ʣ • Bartosz Milewski's Programming Cafe | Category Theory, Haskell,

Concurrency, C++ • ! Bartosz Milewski - YouTube • ! TheCatsters - YouTube • Category theory for beginners • ݍ࿦ษڧձ @ ϫʔΫεΞϓϦέʔγϣϯζ
98. ࢀߟจݙʢதʙ্ڃऀ޲͚ʣ • ! ݍ࿦ ݪஶୈ2൛ | Steve Awodey • !

ϕʔγοΫݍ࿦ ීวੑ͔Βͷ଎शίʔε | Tom Leinster • ! ݍ࿦ͷجૅ | Saunders MacLane • ݍ࿦ | ұେ੔Ҭ • ᐻࢁਖ਼޾ͷΩϚΠϥࣂҭه • nLab