計算ファースト vs. 型ファースト / Computation First vs. Type First

13544f14cbbbd7f170dca2565d5aff87?s=47 INA Lintaro
November 28, 2019

計算ファースト vs. 型ファースト / Computation First vs. Type First

詳しい説明はこちらにあります:
https://tarao.hatenablog.com/entry/type-first

13544f14cbbbd7f170dca2565d5aff87?s=128

INA Lintaro

November 28, 2019
Tweet

Transcript

  1. ܭࢉϑΝʔετ vs. ܕϑΝʔετ ϓϩάϥϜ͞Μ:ʮసੜͨ͠Βূ໌ͩͬͨ݅ʯ ҏಸ ྛଠ࿠ id:tarao @oarat 2019-11-28 ࣾ಺ٕज़ษڧձ

    (վగ൛)
  2. ܭࢉϑΝʔετͰߟ͑Δܕ

  3. ܕ͕ͳ͍ͱ let apply2 = (f, n) => f(f(n)) apply2(1, 3)

    Uncaught TypeError: f is not a function let omega = (x) => x(x) omega(omega) Uncaught RangeError: Maximum call stack size ex- ceeded
  4. ॻ͍ͯΑ͍ࣜΛ੍ݶ͢Δ ▶ ܕ෇͚نଇʹ߹கͨ͠΋ͷͷΈڐ͢ ▶ ྫ: ୯७ܕ෇ϥϜμܭࢉ (STLC) [Church 1940] x

    : T ∈ Γ Γ ⊢ x : T (Var) Γ, x : ⌊S⌋ ⊢ m : T Γ ⊢ ((x:S) => m) : ⌊S⌋ → T (Abs) Γ ⊢ m : S → T Γ ⊢ n : S Γ ⊢ m(n) : T (App) ⌊(x:S) => T⌋ = ⌊S⌋ → ⌊T⌋ (otherwise) ⌊T⌋ = T ڐ͞ΕΔྫ: <A>(f: (a:A) => A) => (n: A) => f(f(n)) f : A → A ∈ {f : A → A, n : A} f : A → A, n : A ⊢ f : A → A f : A → A ∈ {f : A → A, n : A} f : A → A, n : A ⊢ f : A → A n : A ∈ {f : A → A, n : A} f : A → A, n : A ⊢ n : A f : A → A, n : A ⊢ f(n) : A (App) f : A → A, n : A ⊢ f(f(n)) : A (App) f : A → A ⊢ ((n: A) => f(f(n))) : A → A (Abs) ⊢ ((f: (a:A) => A) => (n: A) => f(f(n))) : (A → A) → A → A (Abs)
  5. ॻ͍ͯΑ͍ࣜΛ੍ݶ͢Δ ▶ ܕ෇͚نଇʹ߹கͨ͠΋ͷͷΈڐ͢ ▶ ྫ: ୯७ܕ෇ϥϜμܭࢉ (STLC) [Church 1940] x

    : T ∈ Γ Γ ⊢ x : T (Var) Γ, x : ⌊S⌋ ⊢ m : T Γ ⊢ ((x:S) => m) : ⌊S⌋ → T (Abs) Γ ⊢ m : S → T Γ ⊢ n : S Γ ⊢ m(n) : T (App) ⌊(x:S) => T⌋ = ⌊S⌋ → ⌊T⌋ (otherwise) ⌊T⌋ = T ڐ͞Εͳ͍ྫ: <A, B>(x: (a:A) => B) => x(x) x : A → B ∈ {x : A → B} x : A → B ⊢ x : A → B (Var) x : A ̸∈ {x : A → B} x : A → B ⊢ x : A (Var) x : A → B ⊢ x(x) : B (App) ⊢ ((x: (a:A) => B) => x(x)) : (A → B) → B (Abs)
  6. ॻ͍ͯΑ͍ࣜΛ੍ݶ͢Δ let apply2 = <A>(f: (a: A) => A, n:

    A) => f(f(n)) apply2(1, 3) Argument of type ’1’ is not assignable to parame- ter of type ’(a: 3) => 3’ apply2((n) => n*n, 3) // OK let omega = <A, B>(x: (a: A) => B) => x(x) Argument of type ’(a: A) => B’ is not assignable to pa- rameter of type ’A’
  7. STLCͷੑ࣭ ܕͷ͍ͭͨࣜ͸ ▶ ࣮ߦͨ݁͠Ռͷ஋΋ಉ͡ܕʹͳΔ ▶ ࠷ऴ݁Ռ͚ͩͰͳ࣮͘ߦ్த΋ಉ༷ ▶ ओ෦؆໿ఆཧ (subject reduction)

    ͱݴ͏ ▶ ࣮ߦͨ͠Βඞͣఀࢭ͢Δ (ඞͣ݁Ռͷ஋͕ಘΒΕΔ) ▶ ධՁઓུʹΑΒͳ͍ ▶ ڧਖ਼نԽੑ (strong normalization) ͱݴ͏
  8. STLCͷݶք ▶ νϡʔϦϯά׬શͰ͸ͳ͍ (࠶ؼؔ਺͸ॻ͚ͳ͍) ▶ Ұݟ͢Δͱ໰୊ͳ͍ͷʹॻ͚ͳ͍͕ࣜ͋Δ ܕͳ͠ let apply2 =

    (f, n) => f(f(n)) apply2((n) => [n], 3) => [[3]] ܕ͖ͭ let apply2 = <A>(f: (a: A) => A, n: A) => f(f(n)) apply2((n) => [n], 3) Type ’number[]’ is not assignable to type ’number’
  9. (ऄ଍) ͦ΋ͦ΋ܕͱ͸ ܕͱ͸ ▶ σʔλͷϝϞϦϨΠΞ΢τͷҧ͍Ͱ͸ͳ͍ ▶ ΋ͷͷू·ΓΛ۠ผ͍ͨ֓͠೦Ͱ෼͚ͨ΋ͷ ܕͷىݯ [Kamareddine et

    al. 2002] ▶ ݹ͘͸ϢʔΫϦου ▶ ʮ఺ʯͱʮઢʯΛ۠ผ͍ͯͨ͠ ▶ Theory of types [Russell 1908] ▶ ϥοηϧͷύϥυοΫεͷճආͷͨΊ ▶ ୯७ܕ෇ϥϜμܭࢉ [Church 1940]
  10. (ऄ଍) ͳͥSTLC͸࠶ؼͳ͠? ▶ ౰࣌·ͩίϯϐϡʔλ͸ͳ͔ͬͨ ▶ ΋ͱ΋ͱ͸໋୊ؔ਺ (࿦ཧࣜΛͱΔؔ਺) Λ૝ఆ ▶ ϥοηϧͷύϥυοΫεͷճආ

    ▶ Λ΋ͬͱఆࣜԽͨ͠΋ͷ ▶ ७ਮʹ࿦ཧ্ֶͷٞ࿦ͩͬͨ
  11. ͜͜·Ͱͷ·ͱΊ ▶ ܕ͕ͳ͍ͱΊͪΌͪ͘ΌʹͳΔ ▶ ܕͰʮඞͣ͏·͘ಈ͘ʯ΋ͷʹ੍ݶ ▶ ੍ݶ͗ͯ͢͠ෆศʹݟ͑Δ?

  12. ܕϑΝʔετͰߟ͑Δܭࢉ

  13. ܕ͸͋Δछͷ࢓༷ ྫ (Scala) BookmarkRepository.find: BookmarkId => Option[BookmarkEntity] // - ϒοΫϚʔΫ

    ID ͕͋ΔͳΒ, // - ϒοΫϚʔΫͷΤϯςΟςΟ͕͋Ε͹ಘΒΕΔ Seq.sortBy: Seq[A] => (A => B) => Ordering[B] => Seq[A] // - A ͷྻ͕͋Γ, // - A Λ B ʹม׵Ͱ͖, // - B ͷॱং͕نఆ͞Ε͍ͯΕ͹, // - (B ͰιʔτࡁΈͷ)A ͷྻ͕ಘΒΕΔ Either.fold: Either[A, B] => (A => C) => (B => C) => C // - A ·ͨ͸ B ͲͪΒ͔ͷΠϯελϯε͕͋Γ, // - A ͔Β C ΁ͷม׵ͱ, B ͔Β C ΁ͷม׵͕͋Ε͹, // - ৗʹ C ͷΠϯελϯε͕ಘΒΕΔ
  14. ܕ͸͋Δछͷ࢓༷ ܕͷಡΈํ ▶ ܕA͸ʮAͷΠϯελϯε͕͋ΔʯΛදͯͦ͠͏ ▶ =>͸ʮͳΒ͹ʯΛදͯͦ͠͏

  15. ܕ͸͋Δछͷ࢓༷ ܕͷಡΈํ ▶ ܕA͸ʮAͷΠϯελϯε͕͋ΔʯΛදͯͦ͠͏ ▶ =>͸ʮͳΒ͹ʯΛදͯͦ͠͏ → ࣮ࡍͦ͏

  16. ܕ͸͋Δछͷ࢓༷ ܕͷಡΈํ ▶ ܕA͸ʮAͷΠϯελϯε͕͋ΔʯΛදͯͦ͠͏ ▶ =>͸ʮͳΒ͹ʯΛදͯͦ͠͏ → ࣮ࡍͦ͏ ܕ͸࿦ཧࣜ, ࣮૷͸ূ໌

    ▶ ܕ = ࢓༷ (࿦ཧࣜͰද໋ͨ͠୊) ▶ ܕͷ͍ͭͨࣜ = ࢓༷͕ຬͨͤΔ͜ͱͷূ໌ ▶ ࣜʹܕ͕ͭ͘ ⇔ ࢓༷Λຬ࣮ͨ͢૷͕ଘࡏ͢Δ
  17. ܕ͸͋Δछͷ࢓༷ ܕͷಡΈํ ▶ ܕA͸ʮAͷΠϯελϯε͕͋ΔʯΛදͯͦ͠͏ ▶ =>͸ʮͳΒ͹ʯΛදͯͦ͠͏ → ࣮ࡍͦ͏ ܕ͸࿦ཧࣜ, ࣮૷͸ূ໌

    ▶ ܕ = ࢓༷ (࿦ཧࣜͰද໋ͨ͠୊) ▶ ܕͷ͍ͭͨࣜ = ࢓༷͕ຬͨͤΔ͜ͱͷূ໌ ▶ ࣜʹܕ͕ͭ͘ ⇔ ࢓༷Λຬ࣮ͨ͢૷͕ଘࡏ͢Δ Curry-HowardಉܕରԠ
  18. Curry-HowardಉܕରԠ STLC + ௚ੵܕ (λϓϧ) + ௚࿨ܕͷܕ෇͚نଇ Γ, x :

    φ ⊢ x : φ (Ax) Γ ⊢ m : ⊥ Γ ⊢ m : φ (⊥E) Γ, x : ⌊φ⌋ ⊢ m : ψ Γ ⊢ ((x:φ) => m) : ⌊φ⌋ → ψ (→I) Γ ⊢ m : φ → ψ Γ ⊢ n : φ Γ ⊢ m(n) : ψ (→E) Γ ⊢ m : φ Γ ⊢ n : ψ Γ ⊢ [m, n] : φ ∧ ψ (∧I) Γ ⊢ m : φ ∧ ψ Γ ⊢ m[0] : φ (∧E) Γ ⊢ m : φ ∧ ψ Γ ⊢ m[1] : ψ Γ ⊢ m : φ kind distinct in φ, ψ Γ ⊢ m : φ ∨ ψ (∨I) Γ ⊢ m : ψ kind distinct in φ, ψ Γ ⊢ m : φ ∨ ψ Γ ⊢ m : φ ∨ ψ Γ ⊢ n1 : φ → ϑ Γ ⊢ n2 : ψ → ϑ kind : Ki in φ, ψ Γ ⊢ switch (m.kind) { case Ki: return ni(m); ... } : ϑ (∨E)
  19. Curry-HowardಉܕରԠ ௚؍ओ໋ٛ୊࿦ཧ (Gentzen ͷ NJ) Γ, x : φ ⊢

    x : φ (Ax) Γ ⊢ m : ⊥ Γ ⊢ m : φ (⊥E) Γ, x : ⌊φ⌋ ⊢ m : ψ Γ ⊢ ((x:φ) => m) : ⌊φ⌋ → ψ (→I) Γ ⊢ m : φ → ψ Γ ⊢ n : φ Γ ⊢ m(n) : ψ (→E) Γ ⊢ m : φ Γ ⊢ n : ψ Γ ⊢ [m, n] : φ ∧ ψ (∧I) Γ ⊢ m : φ ∧ ψ Γ ⊢ m[0] : φ (∧E) Γ ⊢ m : φ ∧ ψ Γ ⊢ m[1] : ψ Γ ⊢ m : φ kind distinct in φ, ψ Γ ⊢ m : φ ∨ ψ (∨I) Γ ⊢ m : ψ kind distinct in φ, ψ Γ ⊢ m : φ ∨ ψ Γ ⊢ m : φ ∨ ψ Γ ⊢ n1 : φ → ϑ Γ ⊢ n2 : ψ → ϑ kind : Ki in φ, ψ Γ ⊢ switch (m.kind) { case Ki: return ni(m); ... } : ϑ (∨E)
  20. ͳͥܕϑΝʔετ?

  21. ͳͥܕϑΝʔετ? ԿΛূ໌͍͔ܾͨ͠Ίͣʹ ূ໌Λॻ͘Ϡπ͸͍ͳ͍

  22. ͳͥܕϑΝʔετ? ԿΛূ໌͍͔ܾͨ͠Ίͣʹ ূ໌Λॻ͘Ϡπ͸͍ͳ͍ ▶ ҋӢʹίʔυΛॻ͘લʹ࢓༷Λߟ͑·͠ΐ͏ ▶ ܕ͕ͳͯ͘΋ TDD Ͱ͸ͦ͏͠·͢ΑͶ

  23. (ऄ଍) ຊ౰ʹ໋୊͕ઌ? ࣮ࡍʹূ໌Λॻ͍͍ͯΔͱ͖͸ ▶ ิ୊Λॻ͘ͱ͖͸ޙ͔Β໋୊Λม͑Δ͜ͱ΋ ▶ ͍͟࢖͏ͱ͖ʹ࢖͍উखͷѱ͞ʹؾͮ͘ ▶ ͏·͘ূ໌Ͱ͖ͳ͍ͷͰϓϥϯ B

    ʹม͑Δ ▶ ͱ͸͍͍͖͑ͳΓূ໌Λॻ͘͜ͱ͸ͳͦ͞͏ ϓϩάϥϜΛॻ͘ͱ͖Ͳ͏ͨ͠ΒΑ͍? ▶ ϓϥΠϕʔτϝιου౳͸޷͖ʹͨ͠ΒΑ͍ ▶ ʮͳʹ͕੒Γཱͭ͸͔ͣ?ʯ͸৺͕͚͍ͨ
  24. ܕ͸ʮ͋Δछʯͷ࢓༷ ܕͷදݱྗ͕ߴ͍ͱخ͍͠ ▶ ࢓༷ͷදݱྗ͸ܕͷදݱྗʹґଘ ܕͷදݱྗ͕ߴ͗͢ΔͱࠔΔ ▶ ΍Γ͗͢Δͱܕݕ͕ܾࠪఆෆೳʹͳΔ ▶ ܕਪ࿦͕׬શͰ͸ͳ͘ͳΓ͕ͪ ▶

    ϓϩάϥϜͰ͸ͳ͘೉͍͠ূ໌Λॻ͘͜ͱʹ ▶ Coq ͳͲ ▶ ূ໌Λॻ͍͔ͯͦ͜ΒϓϩάϥϜΛநग़
  25. දݱྗͷߴ͍ܕ ࿦ཧମܥ ܭࢉମܥ΍ݴޠ ݹయ࿦ཧ STLC + ܧଓ ೋ֊௚؍ओ໋ٛ୊࿦ཧ System F

    ࣌૬࿦ཧ MetaOCaml ઢܗ࿦ཧ (ΞϑΟϯ࿦ཧ) Rust
  26. ͜͜·Ͱͷ·ͱΊ ▶ ࣜʹܕ͕ͭ͘ = ࢓༷Λຬ࣮ͨ͢૷͕Ͱ͖ͨ ▶ ܕ = ࢓༷ ▶

    ࣮૷ = ࢓༷ͷ࣮ݱΛূ໌ ▶ ;ͭ͏࢓༷͔Βઌʹߟ͑Δ ▶ ܕͷදݱྗΛߴΊΔͱࡉ͔͍࢓༷ΛදݱͰ͖Δ ▶ දݱྗͷߴ͍࿦ཧମܥ΋͋Δ (Ή͔͍ͣ͠) ▶ ଞʹ΋޻෉ͷ͔ͨ͠͸͋Δ (͜ͷ͋ͱ঺հ)
  27. ܕͷදݱΛ޻෉͢Δ

  28. Scalaͷimplicit ྫ val l1: List[(Int, String)] = List(1 -> "foo",

    2 -> "bar") val m1 = l1.toMap // m1: Map[Int, String] val l2: List[Int] = List(1, 2, 3) val m2 = l2.toMap // ίϯύΠϧΤϥʔ Ͳ͏΍ͬͯఆٛ͢Δ?? class List[A] { def toMap: Map[???]
  29. Scalaͷimplicit ྫ val l1: List[(Int, String)] = List(1 -> "foo",

    2 -> "bar") val m1 = l1.toMap // m1: Map[Int, String] val l2: List[Int] = List(1, 2, 3) val m2 = l2.toMap // ίϯύΠϧΤϥʔ Ͳ͏΍ͬͯఆٛ͢Δ?? class List[A] { def toMap[K, V](implicit ev: A <:< (K, V) // ௥Ճͷূ໌Λཁٻ ): Map[K, V]
  30. εϚʔτίϯετϥΫλ ྫ: ϦετΛඇۭʹݶఆ͍ͨ͠ val l1 = List(1, 2, 3) l1.head

    // => 1 val l2 = List() l2.head // ࣮ߦ࣌Τϥʔ class Nel[A] private (val v: List[A]) object Nel { def apply[A](v: A*): Option[Nel[A]] = if (v.nonEmpty) Some(new Nel(v)) else None } val nel1 = Nel(1, 2, 3) nel1.map(_.v.head) // => Some(1) val nel2 = Nel() nel2.map(_.v.head) // => None
  31. ɹ ;Δ͍ ᝲ ɹܕ (refinement type) ྫ: ϦετͷඇۭੑΛอ͍ͪͨ val Some(nel1)

    = Nel(1, 2, 3) nel1.v.map(n => n * n) // => List(1, 4, 9): List[Int] val Some(nel2) = RefinedNel(1, 2, 3) nel2.map(n => n * n) // => List(1, 4, 9): RefinedNel[Int] nel2.flatMap(n => List()) // => List(): List[Int] ▶ ަࠩܕ (intersection type) Ͱ࣮ݱ [Pfenning et al. 1991] ▶ Haskell ΍ Scala Ͱ͸ Refined ͱ͍͏ϥΠϒϥϦ
  32. ߴΧΠϯυܕ ྫ trait Hoge[F[_]] ▶ ܕίϯετϥΫλΛҾ਺ʹऔΕΔ ▶ ͋Δͱݍ࿦తͳ֓೦Λૉ௚ʹදݱͰ͖Δ ▶ αϙʔτͯ͠Δݴޠ͸ଟ͘͸ͳ͍

    ▶ Haskell, Scala, C++, Rust ͋ͨΓ? ▶ ࢖ͬͯ͏Ε͍͠ྫ͸άά͍ͬͯͩ͘͞
  33. ·ͱΊ ▶ ܕΛ͚ͭͯʮ͏·͘ಈ͘ʯ΋ͷʹ੍ݶ͢Δ ▶ ٯʹ࢓༷͔Βઌʹߟ͑Δ ▶ ࢓༷Λ͏·͘දݱ͢ΔͨΊʹςΫχοΫΛຏ͘