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

多相型、推論、Ruby

Soutaro Matsumoto
March 20, 2017
6.2k

 多相型、推論、Ruby

大江戸Ruby会議06 https://asakusarb.github.io/oedo06/

Soutaro Matsumoto

March 20, 2017
Tweet

Transcript

  1. ଟ૬ܕɺ
    ਪ࿦ɺ
    Ruby দຊफଠ࿠

    @soutaro

    View Slide

  2. View Slide

  3. View Slide

  4. ܕ͸ॻ͖ͨ͘ͳ͍

    View Slide

  5. ܕ͸ॻ͖ͨ͘ͳ͍
    Duck Typingʹͳ͍ͬͯͯཉ͍͠

    View Slide

  6. ܕ͸ॻ͖ͨ͘ͳ͍
    Duck Typingʹͳ͍ͬͯͯཉ͍͠
    ܕਪ࿦

    View Slide

  7. ܕ͸ॻ͖ͨ͘ͳ͍
    Duck Typingʹͳ͍ͬͯͯཉ͍͠
    ܕਪ࿦
    typo͙Β͍͸࣮ߦ͠ͳͯ͘΋ൃݟ͍ͨ͠

    View Slide

  8. ܕ͸ॻ͖ͨ͘ͳ͍
    Duck Typingʹͳ͍ͬͯͯཉ͍͠
    ܕਪ࿦
    typo͙Β͍͸࣮ߦ͠ͳͯ͘΋ൃݟ͍ͨ͠
    ܕ͸ઈରʹॻ͖ͨ͘ͳ͍

    View Slide

  9. ܕ͸ॻ͖ͨ͘ͳ͍
    Duck Typingʹͳ͍ͬͯͯཉ͍͠
    ܕਪ࿦
    typo͙Β͍͸࣮ߦ͠ͳͯ͘΋ൃݟ͍ͨ͠
    ܕ͸ઈରʹॻ͖ͨ͘ͳ͍
    Gradual Typing

    View Slide

  10. ͳΜ͔ྑ͍ײ͡ʹܕ͕͍ͭͨ
    Ruby͕ཉ͍͠
    ܕ͸ॻ͖ͨ͘ͳ͍
    Duck Typingʹͳ͍ͬͯͯཉ͍͠
    ܕਪ࿦
    typo͙Β͍͸࣮ߦ͠ͳͯ͘΋ൃݟ͍ͨ͠
    ܕ͸ઈରʹॻ͖ͨ͘ͳ͍
    Gradual Typing

    View Slide

  11. զʑ͕ཉ͍͠΋ͷ
    ͳΜ͔ྑ͍ײ͡ʹܕ͕͍ͭͨRuby͕ཉ͍͠
    ύϥϝʔλଟ૬ߏ଄తͳ෦෼ܕଟ૬

    ׬શͳܕਪ࿦Ruby

    View Slide

  12. ଟ૬ܕ
    w ύϥϝʔλଟ૬Parametric Polymorphism
    w ෦෼ܕଟ૬Subtyping Polymorphism
    w ΞυϗοΫଟ૬Ad-hoc Polymorphism
    จ຺ʹԠͯ͡ɺҰఆͷ੍ݶͷݩͰɺ

    ࣜʹ͍Ζ͍ΖͳܕΛ༩͑Δ

    View Slide

  13. ෦෼ܕଟ૬
    w ෦෼ܕ

    “String is a Object”
    interface X {
    void f(Object x);
    }
    X x = …;
    x.f("Ruby");
    x.f(new ArrayList());

    View Slide

  14. ෦෼ܕଟ૬
    w ෦෼ܕ

    “String is a Object”
    interface X {
    void f(Object x);
    }
    X x = …;
    x.f("Ruby");
    x.f(new ArrayList());
    Ҿ਺ͷܕ͸String

    View Slide

  15. ෦෼ܕଟ૬
    w ෦෼ܕ

    “String is a Object”
    interface X {
    void f(Object x);
    }
    X x = …;
    x.f("Ruby");
    x.f(new ArrayList());
    Ҿ਺ͷܕ͸String
    Ҿ਺ͷܕ͸ArrayList

    View Slide

  16. ໊લతɾߏ଄త
    w ໊લతNominal

    ΫϥεఆٛͰએݴͯ͠෦෼ܕؔ܎Λఆٛ
    w ߏ଄తStructual

    ϝιουఆٛͷแؚؔ܎Ͱ෦෼ܕؔ܎ΛఆٛʢΑΓ
    ॊೈʣ

    View Slide

  17. ܕਪ࿦
    w ʢ׬શͳʣܕਪ࿦
    w ϩʔΧϧܕਪ࿦

    View Slide

  18. ʢ׬શͳʣܕਪ࿦
    [Milner, 1978]
    w શ͘ܕΛॻ͔ͳͯ͘΋ྑ͍

    ʢܕਪ࿦ͷ׬શੑCompletenessʣ
    w ϓϩάϥϛϯάݴޠ΁ͷ੍໿͕େ͖͍ʢMLʣ
    # let has_even_leaf tree =
    exists_leaf (fun n -> n mod 2 = 0) tree;;
    val has_even_leaf : tree -> bool =

    View Slide

  19. ϩʔΧϧܕਪ࿦
    [Pierce, 1997]
    w ϩʔΧϧม਺ͷܕ͸ॻ͔ͳͯ͘΋ྑ͍

    ϝιουͱ͔ͷܕ͸ॻ͘ɻ
    w ͍ΖΜͳϓϩάϥϛϯάݴޠʹಋೖͰ͖Δ

    ʢScala/Swift/C#/C++ʣ
    func greet(person: String) -> String {
    let greeting = "Hello, " + person + "!"
    return greeting
    }

    View Slide

  20. ϩʔΧϧܕਪ࿦
    [Pierce, 1997]
    w ϩʔΧϧม਺ͷܕ͸ॻ͔ͳͯ͘΋ྑ͍

    ϝιουͱ͔ͷܕ͸ॻ͘ɻ
    w ͍ΖΜͳϓϩάϥϛϯάݴޠʹಋೖͰ͖Δ

    ʢScala/Swift/C#/C++ʣ
    func greet(person: String) -> String {
    let greeting = "Hello, " + person + "!"
    return greeting
    } greetingͷܕ͸ਪ࿦͞ΕΔ

    View Slide

  21. ϩʔΧϧܕਪ࿦
    [Pierce, 1997]
    w ϩʔΧϧม਺ͷܕ͸ॻ͔ͳͯ͘΋ྑ͍

    ϝιουͱ͔ͷܕ͸ॻ͘ɻ
    w ͍ΖΜͳϓϩάϥϛϯάݴޠʹಋೖͰ͖Δ

    ʢScala/Swift/C#/C++ʣ
    func greet(person: String) -> String {
    let greeting = "Hello, " + person + "!"
    return greeting
    } greetingͷܕ͸ਪ࿦͞ΕΔ
    ؔ਺ͷܕ͸ॻ͘

    View Slide

  22. զʑ͕ཉ͍͠΋ͷ
    ύϥϝʔλଟ૬ߏ଄తͳ෦෼ܕଟ૬

    ׬શͳܕਪ࿦Ruby
    ͳΜ͔ྑ͍ײ͡ʹܕ͕͍ͭͨRuby͕ཉ͍͠

    View Slide

  23. OCamlͳΜ͔͍ۙͷͰ͸
    ύϥϝʔλଟ૬ߏ଄తͳ෦෼ܕଟ૬

    ׬શͳܕਪ࿦Ruby
    # let f x = print_string x#to_s;;
    val f : < to_s : string; .. >

    -> unit =

    View Slide

  24. OCamlͳΜ͔͍ۙͷͰ͸
    ύϥϝʔλଟ૬ߏ଄తͳ෦෼ܕଟ૬

    ׬શͳܕਪ࿦Ruby
    # let f x = print_string x#to_s;;
    val f : < to_s : string; .. >

    -> unit =
    #Ͱϝιουݺͼग़͠

    View Slide

  25. OCamlͳΜ͔͍ۙͷͰ͸
    ύϥϝʔλଟ૬ߏ଄తͳ෦෼ܕଟ૬

    ׬શͳܕਪ࿦Ruby
    # let f x = print_string x#to_s;;
    val f : < to_s : string; .. >

    -> unit =
    to_sͱ͍͏ϝιου͕͋Ε͹ͳΜͰ΋͍͍
    #Ͱϝιουݺͼग़͠

    View Slide

  26. OCamlͰ͸μϝͳͱ͜Ζ
    w OCaml΋ΦϒδΣΫτͷपΓͰ͸ܕΛॻ͘ඞཁ͕
    ͋Δ
    w OCamlͰ͸ॻ͚ͳ͍ϝιου
    w Array#map String#split

    View Slide

  27. զʑ͕ཉ͍͠΋ͷ
    w ·ʔແཧ

    ͳʹ͔ΛఘΊͳ͍ͱ͍͚ͳ͍ɻ
    ύϥϝʔλଟ૬ߏ଄తͳ෦෼ܕଟ૬

    ׬શͳܕਪ࿦Ruby

    View Slide

  28. զʑ͕ཉ͍͠΋ͷ
    ύϥϝʔλଟ૬ߏ଄తͳ෦෼ܕଟ૬

    ׬શͳܕਪ࿦Ruby

    View Slide

  29. զʑ͕ཉ͍͠΋ͷ
    RubyͷػೳΛ੍ݶ͍ͯͬͯ͠ɺܕਪ࿦Ͱ͖
    ΔΑ͏ʹͳΒͳ͍͔ʁʁ
    ύϥϝʔλଟ૬ߏ଄తͳ෦෼ܕଟ૬

    ׬શͳܕਪ࿦Ruby

    View Slide

  30. eval
    w ແཧ
    w evalͷฦΓ஋ͷܕ͸anyΈ͍ͨͳܕʹͯ͠͠·͑͹
    ͍͍ͷͰ͸ʢGradual Typing [Siek and Taha, 2006]ʣ
    eval(gets)

    View Slide

  31. ActiveRecord
    w DBʹ઀ଓ͠ͳ͍ͱΞτϦϏϡʔτ͕Θ͔Βͳ͍
    w anyͰͳΜͱ͔͠Α͏
    class Person < ApplicationRecord
    belongs_to :group
    has_many :contacts
    end

    View Slide

  32. ϝλϓϩάϥϛϯά
    define_method(:name=) do |x|
    @attributes[:name] = x
    end

    View Slide

  33. ϝλϓϩάϥϛϯά
    class Location
    attr_reader :line
    attr_reader :column
    end

    View Slide

  34. require
    w require͕࣮ߦ͞ΕΔॠؒ·ͰͲͷϓϩάϥϜ͕ಡ·
    ΕΔ͔Θ͔Βͳ͍
    w require͸ϝιουͳͷͰɺ࠶ఆٛͰ͖Δ͠ɺͲ͜
    ʹͰ΋ॻ͚Δ͠ɺҾ਺ʹ͕ࣜॻ͚Δ
    w $LOAD_PATH΋͋ΔΑʂ
    w requireΛߏจʹͯ͠จࣈྻ͔͠ड͚औΕͳ͍ˍτο
    ϓϨϕϧʹ͔͠ॻ͚ͳ͍Α͏ʹ͢Ε͹ྑ͍ͷͰ͸

    View Slide

  35. RubyGems
    ⚰Bundler

    View Slide

  36. RubyΛ੍ݶͯ͠΋͏·͍͔͘ͳ͍
    w ଞʹ΋໰୊͕͋Γɺݱ࣮తͳ੍ݶ͕ݟ͚ͭΒΕͳ͍
    ʢࠓޙɺݟ͔ͭΔ͔΋͠Εͳ͍ʣ
    w ܕΛॻ͔ͳ͍લఏͰ͸ɺҰճanyʹࣦΘΕͨܕ৘ใ
    ΛऔΓ໭͢ํ๏͕ͳ͍

    View Slide

  37. զʑ͕ཉ͍͠΋ͷ
    ύϥϝʔλଟ૬ߏ଄తͳ෦෼ܕଟ૬

    ׬શͳܕਪ࿦Ruby

    View Slide

  38. ͝ఏҊ
    w ߏ଄తͳ෦෼ܕଟ૬ϩʔΧϧܕਪ࿦Gradual Typing
    w ʢΘΓͱʣDuck TypingͰ͖ΔͷͰخ͍͠
    w ॻ͔ͳͯ͘ྑ͍ܕ͸ॻ͔ͳ͍
    w ܕ͕ॻ͍ͯͳ͍ͱ͖͸ࠓͷRubyͱಉ͡
    w ܕͷͨΊͷݴޠ͸Rubyͱผ

    requireͱ͔ΦʔϓϯΫϥεͱ͔ϝλϓϩάϥϛϯάͱ
    ͔͸ߟ͑ͳ͍ɻ

    View Slide

  39. ͍͍ͩͨTypeScript

    View Slide

  40. # group.rbi
    interface String
    def gsub: (Regexp, String) -> String
    end
    interface IGroup
    def people: ActiveRecord.Association
    end
    interface IPerson
    def email: String
    end
    # foo_controller.rb
    group: IGroup = Group.create!(name: name)
    person = group.people.new
    escaped = person.email.map {|x| … }

    View Slide

  41. # group.rbi
    interface String
    def gsub: (Regexp, String) -> String
    end
    interface IGroup
    def people: ActiveRecord.Association
    end
    interface IPerson
    def email: String
    end
    # foo_controller.rb
    group: IGroup = Group.create!(name: name)
    person = group.people.new
    escaped = person.email.map {|x| … }
    ผͷϑΝΠϧͰɺΠϯλʔϑΣΠεΛએݴ͢Δ

    View Slide

  42. # group.rbi
    interface String
    def gsub: (Regexp, String) -> String
    end
    interface IGroup
    def people: ActiveRecord.Association
    end
    interface IPerson
    def email: String
    end
    # foo_controller.rb
    group: IGroup = Group.create!(name: name)
    person = group.people.new
    escaped = person.email.map {|x| … }
    ผͷϑΝΠϧͰɺΠϯλʔϑΣΠεΛએݴ͢Δ
    ΠϯλϑΣʔεʹϝιουͱܕΛએݴ͢Δ

    View Slide

  43. # group.rbi
    interface String
    def gsub: (Regexp, String) -> String
    end
    interface IGroup
    def people: ActiveRecord.Association
    end
    interface IPerson
    def email: String
    end
    # foo_controller.rb
    group: IGroup = Group.create!(name: name)
    person = group.people.new
    escaped = person.email.map {|x| … }
    ผͷϑΝΠϧͰɺΠϯλʔϑΣΠεΛએݴ͢Δ
    ܕ஫ऍ
    ΠϯλϑΣʔεʹϝιουͱܕΛએݴ͢Δ

    View Slide

  44. # group.rbi
    interface String
    def gsub: (Regexp, String) -> String
    end
    interface IGroup
    def people: ActiveRecord.Association
    end
    interface IPerson
    def email: String
    end
    # foo_controller.rb
    group: IGroup = Group.create!(name: name)
    person = group.people.new
    escaped = person.email.map {|x| … }
    ผͷϑΝΠϧͰɺΠϯλʔϑΣΠεΛએݴ͢Δ
    ܕ஫ऍ
    ӈลͷܕ͕Θ͔ΔͷͰɺܕ஫ऍ͸ෆཁ
    ΠϯλϑΣʔεʹϝιουͱܕΛએݴ͢Δ

    View Slide

  45. # group.rbi
    interface String
    def gsub: (Regexp, String) -> String
    end
    interface IGroup
    def people: ActiveRecord.Association
    end
    interface IPerson
    def email: String
    end
    # foo_controller.rb
    group: IGroup = Group.create!(name: name)
    person = group.people.new
    escaped = person.email.map {|x| … }
    ผͷϑΝΠϧͰɺΠϯλʔϑΣΠεΛએݴ͢Δ
    ܕ஫ऍ
    ӈลͷܕ͕Θ͔ΔͷͰɺܕ஫ऍ͸ෆཁ
    person.emailͷܕ͕StringͩͱΘ
    ͔ΔͷͰɺmap͕ͳ͍͜ͱ͕Θ͔Δ
    ΠϯλϑΣʔεʹϝιουͱܕΛએݴ͢Δ

    View Slide

  46. ܕ஫ऍ͕ͳ͚Ε͹͜Ε·ͰͷRubyͱಉ͡
    group = Group.create!(name: name)
    person = group.people.new
    escaped = person.email.map {|x| … }

    View Slide

  47. ܕ஫ऍ͕ͳ͚Ε͹͜Ε·ͰͷRubyͱಉ͡
    group = Group.create!(name: name)
    person = group.people.new
    escaped = person.email.map {|x| … }
    ܕ஫ऍ͕ͳ͍ͷͰશ෦anyʹͳΔԿ΋ݕࠪ͠ͳ͍

    View Slide

  48. ܕ஫ऍ͕ͳ͚Ε͹͜Ε·ͰͷRubyͱಉ͡
    group = Group.create!(name: name)
    person = group.people.new
    escaped = person.email.map {|x| … }
    map͕ແ͍͜ͱ͸࣮ߦ࣌ʹൃ֮
    ܕ஫ऍ͕ͳ͍ͷͰશ෦anyʹͳΔԿ΋ݕࠪ͠ͳ͍

    View Slide

  49. # group.rbi
    interface String
    def gsub: (Regexp, String) -> String
    ...
    end
    interface IGroup
    def people: ActiveRecord.Association
    end
    interface IPerson
    def email: String
    end
    # foo_controller.rb
    group: IGroup = Group.create!(name: name)
    person = group.people.new
    escaped = person.email.map {|x| … }

    View Slide

  50. – Rubyͷ෕Matz
    lܕ͸ઈରॻ͖ͨ͘ͳ͍z

    View Slide

  51. w Group.create!ͷܕ͕GroupʹͳΔͷ͸Θ͔Βͳ͍ͷʁ

    Groupͷܕ͕Θ͔ΔͱࢥͬͯΔͷʁʁ
    w ܕΛҰͭ΋ॻ͍͍ͯͳ͍ͱͳʹ΋Θ͔Βͳ͍ͷʁʁ

    ϦςϥϧͳΜ͔͸Θ͔Δ͸ͣɻҙ֎ͱ͍Ζ͍Ζݟ͔ͭΔͷͰ͸ɻ
    w Ϋϥεఆٛʹ͸ܕΛॻ͚ͳ͍ͷʁΦʔϓϯΫϥε͸Ͳ͏ͳΔͷʁ

    ࠓޙͷ՝୊ɻΦʔϓϯΫϥεͱ0CKFDUJWF$ͷ$BUFHPSZͳΜ͔
    ͸͍ۙؾ͕͢Δɻ
    w ࣮૷͸ͳ͍ͷʁ

    Α͘ݟΔͱɺʢܕ஫ऍΛίϝϯτͱ͔Ͱॻ͘͜ͱʹ͢Ε͹ʣ͙͢
    ʹ࣮૷Ͱ͖Δͳ͜Εʜʜ

    View Slide