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

型なし言語のための型

 型なし言語のための型

富山Ruby会議01

Soutaro Matsumoto

November 03, 2019
Tweet

More Decks by Soutaro Matsumoto

Other Decks in Programming

Transcript

  1. ܕͳ͠ݴޠͷͨΊͷܕ
    দຊफଠ࿠

    !TPVUBSP

    View full-size slide

  2. Ruby3ͷܕݕࠪ
    • RubyϓϩάϥϜͷࣜͷܕΛ࣮ߦͤͣʹ൑ఆ͠ɺ։ൃͷମݧΛվળ͢Δ

    • ύϑΥʔϚϯε͸໨తͰ͸ͳ͍
    conf = Conference.find_by!(name: "෋ࢁRubyձٞ", volume: 1)
    conf.talks.each do |talk|
    puts talk.speaker.email
    end

    View full-size slide

  3. Ruby3ͷܕݕࠪ
    • RubyϓϩάϥϜͷࣜͷܕΛ࣮ߦͤͣʹ൑ఆ͠ɺ։ൃͷମݧΛվળ͢Δ

    • ύϑΥʔϚϯε͸໨తͰ͸ͳ͍
    conf = Conference.find_by!(name: "෋ࢁRubyձٞ", volume: 1)
    conf.talks.each do |talk|
    puts talk.speaker.email
    end
    ::Conference

    View full-size slide

  4. Ruby3ͷܕݕࠪ
    • RubyϓϩάϥϜͷࣜͷܕΛ࣮ߦͤͣʹ൑ఆ͠ɺ։ൃͷମݧΛվળ͢Δ

    • ύϑΥʔϚϯε͸໨తͰ͸ͳ͍
    conf = Conference.find_by!(name: "෋ࢁRubyձٞ", volume: 1)
    conf.talks.each do |talk|
    puts talk.speaker.email
    end
    ::Conference
    () { (::Talk) -> void } -> self

    View full-size slide

  5. Ruby3ͷܕݕࠪ
    • RubyϓϩάϥϜͷࣜͷܕΛ࣮ߦͤͣʹ൑ఆ͠ɺ։ൃͷମݧΛվળ͢Δ

    • ύϑΥʔϚϯε͸໨తͰ͸ͳ͍
    conf = Conference.find_by!(name: "෋ࢁRubyձٞ", volume: 1)
    conf.talks.each do |talk|
    puts talk.speaker.email
    end
    ::String
    ::Conference
    () { (::Talk) -> void } -> self

    View full-size slide

  6. ૬ؔਤ
    type-profiler
    Steep
    Sorbet
    RDL
    RBS (stdlib types)
    Level 1 ܕݕࠪ
    Level 2 ܕݕࠪ
    Type signature language

    View full-size slide

  7. ૬ؔਤ
    type-profiler
    Steep
    Sorbet
    RDL
    RBS (stdlib types)
    Level 1 ܕݕࠪ
    Level 2 ܕݕࠪ
    Type signature language
    ࢖༻
    ࢖༻

    View full-size slide

  8. ૬ؔਤ
    type-profiler
    Steep
    Sorbet
    RDL
    RBS (stdlib types)
    Level 1 ܕݕࠪ
    Level 2 ܕݕࠪ
    Type signature language
    ࢖༻
    ࢖༻
    Ruby3ʹಉࠝ ޷͖ͳ΋ͷΛΠϯετʔϧ

    View full-size slide

  9. 3#4SVCZTJHOBUVSF
    w 3#4ΛಡΜͰɺΫϥεఆٛͷ৘ใΛॲཧ͢ΔϥΠϒϥϦ
    w ৄ͘͠͸དྷिͷ3VCZ)BDL$IBMMFOHF)PMJEBZͰ

    IUUQTSIDDPOOQBTTDPNFWFOU
    class Set[A]
    def initialize: (_Each[A, untyped]) -> void
    | () -> void
    def intersection: (_Each[A, untyped]) -> self
    ...
    end

    View full-size slide

  10. Ξ΢τϥΠϯ
    w 3VCZͷ࿩
    w ܕͳ͠ݴޠͷͨΊͷܕ
    w 5ZQF4DSJQUͱ࠷ۙͷྲྀΕ
    w 3VCZͷͨΊͷܕ

    View full-size slide

  11. ܕͳ͠ݴޠͷͨΊͷܕ
    w ܕ
    w ίϯύΠϧ࣌ʹ൑໌͢Δࣜͷଐੑ
    w ͋ΔछͷޡΓΛݕग़Ͱ͖Δʢܕݕࠪʣ
    w ܕͳ͠ݴޠ
    w ίϯύΠϧ࣌ʹܕݕࠪ͞Εͳ͍ݴޠʢ㲈ಈతܕ෇͚ݴޠʣ
    w 3VCZͱ͔

    View full-size slide

  12. ίʔυฤू
    ίϯύΠϧ
    ࣮ߦ
    ܕݕࠪ
    ίʔυฤू
    ίϯύΠϧ
    ࣮ߦ
    ܕݕࠪ

    View full-size slide

  13. class Person
    def name
    @name
    end
    def name=(value)
    @name = value
    end
    end
    if rand(10) < 5
    person = Person.new
    person.nme = "Soutaro Matsumoto" # NoMethodError
    end
    w ܕݕࠪʹΑͬͯɺ໢ཏతʹʢJGͷத΋ʣݕࠪ͞Εͯɺ࣮
    ߦલʹ໰୊͕ݕग़͞ΕΔʢίϯύΠϧ࣌ʣ
    w ܕݕࠪ͠ͳ͍৔߹ʹ͸ɺϓϩάϥϜͷ࣮ߦঢ়گʹΑͬ
    ͯ͸ɺ໰୊͕ݟ͔ͭΒͳ͍ʢ࣮ߦ࣌ʣ

    View full-size slide

  14. ܕݕࠪͷಘࣦ
    w ໰୊͕ࣄલʹݕग़Ͱ͖Δ
    w ໢ཏతͳݕࠪʢ࣮ߦͷύεʹґଘ͠ͳ͍ʣ
    w ॻ͚ΔϓϩάϥϜʹ੍ݶ͕ՃΘΔ
    w ࣮ࡍʹ͸࣮ߦ͞Εͳ͍ύεʹ͍ͭͯ΋ݕࠪ͞Εͯ͠·͏

    View full-size slide

  15. 4DIFNF 4.- )BTLFMM
    +BWB 3VCZ +BWB4DSJQU 1)1
    1ZUIPO
    5ZQF4DSJQU
    4XJGU

    View full-size slide

  16. 4DIFNF 4.- )BTLFMM
    +BWB 3VCZ +BWB4DSJQU 1)1
    1ZUIPO
    5ZQF4DSJQU
    4XJGU
    ܕਪ࿦
    4PGU5ZQJOH
    (FOFSJDT '+

    (SBEVBM5ZQJOH

    View full-size slide

  17. 4DIFNF 4.- )BTLFMM
    +BWB 3VCZ +BWB4DSJQU 1)1
    1ZUIPO
    5ZQF4DSJQU
    4XJGU
    ܕਪ࿦
    4PGU5ZQJOH
    (FOFSJDT '+

    (SBEVBM5ZQJOH

    View full-size slide

  18. 4DIFNF 4.- )BTLFMM
    +BWB 3VCZ +BWB4DSJQU 1)1
    1ZUIPO
    5ZQF4DSJQU
    4XJGU
    ܕਪ࿦
    4PGU5ZQJOH
    (FOFSJDT '+

    (SBEVBM5ZQJOH

    View full-size slide

  19. .-ͷܕਪ࿦
    w ʮ࠙੾ஸೡʹશ෦ͷࣜʹܕΛॻ͔ͳͯ͘΋ྑ͍ʯͱ͍͏ൃݟ
    w ύϥϝʔλଟ૬ʢେମ(FOFSJDTͷ͜ͱʣ
    # let rec map f xs = match xs with
    [] -> []
    | x::xs -> f x :: map f xs;;
    val map : ('a -> 'b) -> 'a list -> 'b list =

    View full-size slide

  20. 4PGU5ZQJOH
    w ܕͳ͠ͷݴޠʹ΋ܕΛ෇͚͍ͨ
    w ܕ͕͍ͭͨ෦෼͸Τϥʔ͕ݕग़Ͱ͖Δ
    w Θ͔Βͳ͍΋ͷ͸࣮ߦ࣌ʹݕࠪ͢Δ
    w ಈ͘ϓϩάϥϜ͸Ͱ͖Δ͚ͩͦͷ··ܕݕࠪΛ௨͍ͨ͠
    w ܕ஫ऍ͸ઈରॻ͖ͨ͘ͳ͍

    View full-size slide

  21. 6OJPOUZQFT
    def f(x)
    if x
    1
    else
    "2"
    end
    end

    View full-size slide

  22. 6OJPOUZQFT
    def f(x)
    if x
    1
    else
    "2"
    end
    end
    (bool) -> (Integer | String)

    View full-size slide

  23. 'MPXTFOTJUJWF5ZQJOH
    def g(n)
    n.abs # NoMethodError
    n.bytes # n: Integer | String
    case n
    when Integer
    n.abs # n: Integer
    when String
    n.bytes # n: String
    end
    end
    (Integer | String) -> Integer

    View full-size slide

  24. 4PGU5ZQJOH
    w 4DIFNFϓϩάϥϜͷܕ෇͚ʹඞཁͳ΋ͷ͕Θ͔ͬͨ
    w 6OJPOUZQFT 'MPXTFOTJUJWFUZQJOH
    w ࣮૷
    w .-ͷܕਪ࿦ʹجͮ͘΋ͷ
    w ϑϩʔղੳ͢Δ΋ͷ

    View full-size slide

  25. ΋ͬͱۙ୅తͳݴޠͰ͸ʁ
    w +BWB4DSJQUͱ͔3VCZͱ͔< >
    w ΦϒδΣΫτʹର͢Δଟ૬ੑ BLBμοΫλΠϐϯά

    w ʮ͋Δϝιου͕ఆٛ͞Ε͍ͯΔ೚ҙͷΫϥεʯΈ͍ͨͳܕ
    def add(x, y)
    x + y
    end
    def add: [A, B] ({ +: (A) -> B }, A) -> B

    View full-size slide

  26. 3VCZͰࢼͨ͠ͱ͜Ζ
    w ΍ͬͺΓݫ͍͠
    w .-ͷܕਪ࿦Ͱ͸ॲཧͰ͖ͳ͍ఆ͕ٛͰͯ͘Δ "SSBZNBQ

    w Ϋϥεఆ໋͕ٛྩతʹมΘ͍ͬͯ͘ͷ͕ݫ͍͠ʢϝλϓϩάϥϛϯάʣ
    w ͦ΋ͦ΋յΕ͍ͯΔఆ͕ٛͨ͘͞Μ͋Δ
    w "SSBZTFMFDUWT0CKFDUTFMFDU
    w )BTIΛฦ͢IBTIΛఆٛͨ͜͠ͱ͕ͳ͍ਓ

    View full-size slide

  27. "SSBZJTB0CKFDU
    w 0CKFDUʹରͯ͠ಈ͘ϓϩάϥϜ͸"SSBZʹରͯ͠΋ಈ͘ʁʁ
    class Object
    def use_select
    select [STDIN], [], []
    end
    end
    "".use_select # OK
    [1,2,3].use_select # ????

    View full-size slide

  28. 4PGU5ZQJOH͔ΒಘΒΕͨ஌ݟ
    w ࿦จͰ͸੒ޭ͍ͯ͠ΔΑ͏ʹݟ͑Δ͕࣮༻Ϩϕϧͷ΋ͷ͸ͳ͍
    w ඞཁͦ͏ͳܕγεςϜͷػೳ͸Θ͔͖ͬͯͨ
    w Ή͠ΖܕΛॻ͍ͨํ͕ྑ͍ͷͰ͸ʁʁ
    w ϓϩάϥϚͷҙਤΛܕͰදݱ͢Δ
    w ҙਤͱҰக͠ͳ͍ίʔυΛݕग़͢Δ

    View full-size slide

  29. (SBEVBM5ZQJOH
    w ઴ਐతܕ෇͚
    w ܕͳ͠ͷίʔυͱܕ͖ͭͷίʔυΛࠞͥΔ
    w ͩΜͩΜܕΛ෇͚͍ͯ͘
    w ܕ͸ॻ͘

    View full-size slide

  30. ܕͳ͠ݴޠͷͨΊͷܕ
    w ͦΕͳΓʹڧྗͳܕγεςϜ
    w 6OJPOUZQFT qPXTFOTJUJWFUZQJOH HFOFSJDT
    w μοΫλΠϐϯά
    w ߏ଄త෦෼ܕ
    w Ϋϥεͷܧঝؔ܎Λ͋ͱͰมߋͰ͖Δ࢓૊Έ )BTLFMM 4XJGU $

    w (SBEVBM5ZQJOH

    View full-size slide

  31. Ξ΢τϥΠϯ
    w 3VCZͷ࿩
    w ܕͳ͠ݴޠͷͨΊͷܕ
    w 5ZQF4DSJQUͱ࠷ۙͷྲྀΕ
    w 3VCZͷͨΊͷܕ

    View full-size slide

  32. ࠷ۙͷྲྀߦ
    w ܕ͖ͭͷํݴ
    w 5ZQF4DSJQU 5ZQFE4DIFNF
    w ܕ஫ऍͷαϙʔτ
    w 1ZUIPO 1)1

    View full-size slide

  33. 5ZQF4DSJQU
    w ೥ݱࡏͰҰ൪উ͍ͬͯΔܕ͖ͭํݴ
    w λʔήοτݴޠ͸+4ʢϥϯλΠϜ΋+4ʣ
    class Drawer {
    contents: ClothingType[] = [];
    add(object: ClothingType) {
    this.contents.push(object);
    }
    }
    interface Sock { color: string }
    interface TShirt { size: "s" | "m" | "l" }
    const drawer: Drawer = new Drawer()
    drawer.push({ color: "white" })
    drawer.push({ size: "s" })

    View full-size slide

  34. 5ZQF4DSJQUͷ͍͢͝ͱ͜Ζ
    w ܕͳ͠ݴޠʹܕΛ෇͚Δਓྨͷເ͕׎ͬͨ
    w ΈΜͳܕΛॻ͍͍ͯΔͷ͕͍͢͝
    w ߏ଄తͳܕ͚ͩͰͳΜͱ͔ͳͬͯΔͷ͕͍͢͝
    w 6OJPOUZQFTͱ͔qPXTFOTJUJWFUZQFTͱ͔MPHJDBMUZQFTͱ͔͠Εͬͱ
    ೖͬͯΔͷ͕͍͢͝
    w ϥϯλΠϜͱͷ੍໿Λ৐Γӽ͑ͯಈ͍ͯΔͷ͕͍͢͝

    View full-size slide

  35. ܕ͸ॻ͔ͳͯ͘͸͍͚ͳ͍
    w ΑͬΆͲࣗ໌ͳ΋ͷҎ֎͸ॻ͘
    w ϥΠϒϥϦͷܕ͸EFpOJUFMZUZQFEʹू·͍ͬͯΔ
    const numbers: number[] = [1,2,3]
    numbers.map(x => x.toString())

    View full-size slide

  36. ߏ଄తͳܕ
    w Ϋϥεͷܧঝؔ܎Ͱ͸ͳ͘ɺϝιουͷू߹Ͱ෦෼ܕؔ܎Λ൑ఆ͢Δ
    w ߏ଄తͳܕ͚ͩͱ͍͏ͷ͸௝͍͠
    w ໰୊͸͋Δ
    interface ForEach {
    forEach: (fun: (a: A) => void) => void
    }
    const x: ForEach = [1,2,3]

    View full-size slide

  37. ͨ·ͨ·ಉ͡ߏ଄͕͋ͬͨΒʁ
    w 5γϟπͱζϘϯ͕۠ผͰ͖ͳ͘ͳΔ
    w #SBOEFEUZQFͰରԠ͢Δ
    interface TShirt {
    size: "s" | "m" | "l";
    }
    interface Pants {
    size: "s" | "m" | "l";
    }

    View full-size slide

  38. ͨ·ͨ·ಉ͡ߏ଄͕͋ͬͨΒʁ
    w 5γϟπͱζϘϯ͕۠ผͰ͖ͳ͘ͳΔ
    w #SBOEFEUZQFͰରԠ͢Δ
    interface TShirt {
    size: "s" | "m" | "l";
    }
    interface Pants {
    size: "s" | "m" | "l";
    }
    interface TShirt {
    type: "tshirt"
    size: "s" | "m" | "l";
    }
    interface Pants {
    type: "pants"
    size: "s" | "m" | "l";
    }

    View full-size slide

  39. 6OJPO5ZQFT'MPXTFOTJUJWF5ZQJOH
    w OVMMVOEFpOFEͱ͏·͘΍ΕΔΑ͏ʹͳͬͨ
    const x: string | undefined = ...
    // Object is possibly 'undefined'.
    x.toUpperCase()
    if (x) {
    x.toUpperCase()
    }

    View full-size slide

  40. ϥϯλΠϜͷ੍໿
    w +4ͷϥϯλΠϜʹͰ͖ͳ͍͜ͱ͸54Ͱ΋Ͱ͖ͳ͍
    w ʮ͋Δ஋͕ΠϯλʔϑΣʔεʹద߹͍ͯ͠Δ͔ݕ͍ࠪͨ͠ʯ
    w Ϣʔβʔ͕ࣗ෼ͷ੹೚Ͱݕূ͢Δ -PHJDBMUZQFT

    • function isPants(object: any): object is Pants {

    return object.type == "pants"

    }

    View full-size slide

  41. ஌ݟ
    w ਓؒ͸ܕΛॻ͘
    w ʢܕΛॻ͖ͨ͘ͳ͍ਓ͸5ZQF4DSJQUΛ࢖Θͳ͍ͷͰ؍ଌͰ͖ͳ͍ʣ
    w େମ+BWB4DSJQUͷίʔυʹܕ͕ͭ͘
    w 6OJPOUZQFTͱ͔qPXTFOTJUJWFUZQJOHͱ͔͕ॏཁ
    w ߏ଄త෦෼ܕ΋ಈ͘
    w ϥϯλΠϜͷ੍ݶΛ৐Γӽ͑ΔͨΊ޻෉ JTܕ

    View full-size slide

  42. 1ZUIPO
    1)1
    w ϝιουͷܕΛॻ͘ه๏͕ಋೖ͞Εͨ
    w ܕݕࠪ͸࣮ߦ࣌
    w ϝιουݺͼग़͠ͷͱ͖ʹܕݕࠪ͢Δ
    w ੩తͳܕݕࠪث΋։ൃ͞Ε͍ͯΔ
    function sum(int $a, int $b) {
    return $a + $b;
    }

    View full-size slide

  43. Ξ΢τϥΠϯ
    w 3VCZͷ࿩
    w ܕͳ͠ݴޠͷͨΊͷܕ
    w 5ZQF4DSJQUͱ࠷ۙͷྲྀΕ
    w 3VCZͷͨΊͷܕ

    View full-size slide

  44. 3VCZͷͨΊͷܕ
    w 4PGUUZQJOHͷ஌ݟˠਪ࿦ΛؤுΔͷ͸௅ઓతʢ!NBNFʣ
    w 5ZQF4DSJQUͷ஌ݟ
    w ਓྨ͸ܕΛॻ͘
    w ͦΕͳΓʹڧྗͳܕγεςϜ͕͋Ε͹্ख͘΍Εͦ͏
    w 1ZUIPO 1)1ͷ஌ݟ
    w ܕ஫ऍ͸ܾΊͳ͍ͱ͍͚ͳ͍
    w ܕݕࠪث͸ผπʔϧʹ͢Δ

    View full-size slide

  45. ܕ஫ऍͷه๏ 3#4

    w গͳ͘ͱ΋ϥΠϒϥϦͷܕΛॻ͘ํ๏͕ඞཁ
    w ܕݕࠪπʔϧ͕ͦΕͧΕʹ༻ҙ͢Δͷ͸͔ͳΓݫ͍͠
    w ϥϯλΠϜͷݕ͕ࠪͰ͖Δ͚ͩͰ΋ͦΕͳΓʹخ͍͠Ͱ͸ʁ
    w ιʔείʔυʹຒΊࠐΉߏจ͸࠾༻͠ͳ͍

    View full-size slide

  46. ૊ΈࠐΈͷܕ஫ऍߏจʢෆ࠾༻ʣ
    class Box
    extend T::Sig
    extend T::Generic
    Elem = type_member
    sig {returns(Elem)}
    # @type var box: Box[Integer]
    box = Box.new
    box.x = "hello"
    &NCFEEFE%4- 4PSCFU

    $PNNFOUT 4UFFQ

    class Box [A]
    def value: A; ...; end
    def value=(value: A): A; ...; end
    end
    a: Box[Integer] = Box.new

    View full-size slide

  47. ͦΕͳΓʹϦονͳܕ
    w λϓϧɺϨίʔυ

    [Integer, Symbol]
    w Ϧςϥϧܕ

    1, "hello", :world
    w 6OJPOUZQFT

    Integer | String
    w 0QUJPOBMUZQFTɺ(FOFSJDTʜ

    Array[String]?
    w յΕ͍ͯΔ΋ͷ͸JODPNQBUJCMF

    incompatible

    def select: [A] () { (Elem) -> A

    View full-size slide

  48. μοΫλΠϐϯά
    w JOUFSGBDFΛఆٛͯ͠ɺཁٻ͞ΕΔϝιουͷू߹Λॻ͘
    w ϝιου͕͋Δ͔ͳ͍͔Ͱݕࠪ͞ΕΔ
    interface _Push
    def <<: (String) -> void
    end
    def foo: (_Push) -> void
    def foo(a)
    a << "hello"
    end
    foo []
    foo ""
    foo 3 # Τϥʔ

    View full-size slide

  49. ࣮ߦ࣌ݕ͚ࠪͩͰ΋
    w γάωνϟΛॻ͍ͨΒɺϢχοτςετͰςετ͢Δํ๏Λఏڙ
    w ϝιουݺͼग़͠ͷલޙʹܕݕࠪΛૠೖ
    w IUUQTSIDDPOOQBTTDPNFWFOU
    $ RBS_TEST_TARGET='Goodcheck::*' \
    RBS_TEST_RAISE=true \
    RUBYOPT='-rbundler/setup -rruby/signature/test/setup' \
    RBS_TEST_OPT='-rset -rpathname -Isig' \

    bundle exec rake test

    View full-size slide

  50. IUUQTHJUIVCDPNTJEFSHPPEDIFDLUSFFSCT

    View full-size slide

  51. ·ͱΊ
    w 4PGUUZQJOHΈ͍ͨʹਪ࿦ΛؤுΔͷ͸߹ཧతͰ͸ͳ͍
    w ܕΛॻ͔ͳ͍ͷ͸ݫ͍͠
    w ਓؒ͸ܕΛॻ͘ʢ͜͜೥ͰಘΒΕͨ஌ݟʣ
    w 3VCZͷͨΊͷܕ
    w ΘΓͱϦονͳܕ(FOFSJDTɺ6OJPOUZQFTɺ'MPXTFOTJUJWFUZQJOH
    w μοΫλΠϐϯά͸ؤுΔʢߏ଄త෦෼ܕʣ

    View full-size slide

  52. w <$BSUXSJHIU >3$BSUXSJHIUBOE.'BHBO4PGUUZQJOH
    w <.BUTVNPUP >4.BUTVNPUPBOE:.JOBNJEF5ZQF*OGFSFODFGPS3VCZ
    1SPHSBNTCBTFEPO1PMZNPSQIJD3FDPSE5ZQFT
    w <+FOTFO >4)+FOTFOBOE".”MMFSBOE15IJFNBOO 5ZQF"OBMZTJTGPS
    +BWB4DSJQU
    w <4JFL >+4JFLBOE85BIB (SBEVBM5ZQJOHGPS0CKFDUT
    w <)PDITUBEU >45)PDITUBEU 5ZQFE4DIFNF'SPN4DSJQUTUP1SPHSBNT
    w

    View full-size slide