型なし言語のための型

 型なし言語のための型

富山Ruby会議01

1fab9d01b25e99522f3dfd01e3d4cb51?s=128

Soutaro Matsumoto

November 03, 2019
Tweet

Transcript

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

  2. @soutaro

  3. @soutaro

  4. Ruby3ͷܕݕࠪ • RubyϓϩάϥϜͷࣜͷܕΛ࣮ߦͤͣʹ൑ఆ͠ɺ։ൃͷମݧΛվળ͢Δ • ύϑΥʔϚϯε͸໨తͰ͸ͳ͍ conf = Conference.find_by!(name: "෋ࢁRubyձٞ", volume:

    1) conf.talks.each do |talk| puts talk.speaker.email end
  5. Ruby3ͷܕݕࠪ • RubyϓϩάϥϜͷࣜͷܕΛ࣮ߦͤͣʹ൑ఆ͠ɺ։ൃͷମݧΛվળ͢Δ • ύϑΥʔϚϯε͸໨తͰ͸ͳ͍ conf = Conference.find_by!(name: "෋ࢁRubyձٞ", volume:

    1) conf.talks.each do |talk| puts talk.speaker.email end ::Conference
  6. Ruby3ͷܕݕࠪ • RubyϓϩάϥϜͷࣜͷܕΛ࣮ߦͤͣʹ൑ఆ͠ɺ։ൃͷମݧΛվળ͢Δ • ύϑΥʔϚϯε͸໨తͰ͸ͳ͍ conf = Conference.find_by!(name: "෋ࢁRubyձٞ", volume:

    1) conf.talks.each do |talk| puts talk.speaker.email end ::Conference () { (::Talk) -> void } -> self
  7. 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
  8. ૬ؔਤ type-profiler Steep Sorbet RDL RBS (stdlib types) Level 1

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

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

    ܕݕࠪ Level 2 ܕݕࠪ Type signature language ࢖༻ ࢖༻ Ruby3ʹಉࠝ ޷͖ͳ΋ͷΛΠϯετʔϧ
  11. 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
  12. Ξ΢τϥΠϯ w 3VCZͷ࿩ w ܕͳ͠ݴޠͷͨΊͷܕ w 5ZQF4DSJQUͱ࠷ۙͷྲྀΕ w 3VCZͷͨΊͷܕ

  13. ܕͳ͠ݴޠͷͨΊͷܕ w ܕ w ίϯύΠϧ࣌ʹ൑໌͢Δࣜͷଐੑ w ͋ΔछͷޡΓΛݕग़Ͱ͖Δʢܕݕࠪʣ w ܕͳ͠ݴޠ w

    ίϯύΠϧ࣌ʹܕݕࠪ͞Εͳ͍ݴޠʢ㲈ಈతܕ෇͚ݴޠʣ w 3VCZͱ͔
  14. ίʔυฤू ίϯύΠϧ ࣮ߦ ܕݕࠪ ίʔυฤू ίϯύΠϧ ࣮ߦ ܕݕࠪ

  15. 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 ܕݕࠪ͠ͳ͍৔߹ʹ͸ɺϓϩάϥϜͷ࣮ߦঢ়گʹΑͬ ͯ͸ɺ໰୊͕ݟ͔ͭΒͳ͍ʢ࣮ߦ࣌ʣ
  16. ܕݕࠪͷಘࣦ w ໰୊͕ࣄલʹݕग़Ͱ͖Δ w ໢ཏతͳݕࠪʢ࣮ߦͷύεʹґଘ͠ͳ͍ʣ w ॻ͚ΔϓϩάϥϜʹ੍ݶ͕ՃΘΔ w ࣮ࡍʹ͸࣮ߦ͞Εͳ͍ύεʹ͍ͭͯ΋ݕࠪ͞Εͯ͠·͏

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

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

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

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

    ܕਪ࿦ 4PGU5ZQJOH (FOFSJDT '+ (SBEVBM5ZQJOH
  21. .-ͷܕਪ࿦ 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 = <fun>
  22. 4PGU5ZQJOH w ܕͳ͠ͷݴޠʹ΋ܕΛ෇͚͍ͨ w ܕ͕͍ͭͨ෦෼͸Τϥʔ͕ݕग़Ͱ͖Δ w Θ͔Βͳ͍΋ͷ͸࣮ߦ࣌ʹݕࠪ͢Δ w ಈ͘ϓϩάϥϜ͸Ͱ͖Δ͚ͩͦͷ··ܕݕࠪΛ௨͍ͨ͠ w

    ܕ஫ऍ͸ઈରॻ͖ͨ͘ͳ͍
  23. 6OJPOUZQFT def f(x) if x 1 else "2" end end

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

    (bool) -> (Integer | String)
  25. '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
  26. 4PGU5ZQJOH w 4DIFNFϓϩάϥϜͷܕ෇͚ʹඞཁͳ΋ͷ͕Θ͔ͬͨ w 6OJPOUZQFT 'MPXTFOTJUJWFUZQJOH  w ࣮૷ w

    .-ͷܕਪ࿦ʹجͮ͘΋ͷ w ϑϩʔղੳ͢Δ΋ͷ
  27. ΋ͬͱۙ୅తͳݴޠͰ͸ʁ w +BWB4DSJQUͱ͔3VCZͱ͔< > w ΦϒδΣΫτʹର͢Δଟ૬ੑ BLBμοΫλΠϐϯά  w ʮ͋Δϝιου͕ఆٛ͞Ε͍ͯΔ೚ҙͷΫϥεʯΈ͍ͨͳܕ

    def add(x, y) x + y end def add: [A, B] ({ +: (A) -> B }, A) -> B
  28. 3VCZͰࢼͨ͠ͱ͜Ζ w ΍ͬͺΓݫ͍͠ w .-ͷܕਪ࿦Ͱ͸ॲཧͰ͖ͳ͍ఆ͕ٛͰͯ͘Δ "SSBZNBQ  w Ϋϥεఆ໋͕ٛྩతʹมΘ͍ͬͯ͘ͷ͕ݫ͍͠ʢϝλϓϩάϥϛϯάʣ w

    ͦ΋ͦ΋յΕ͍ͯΔఆ͕ٛͨ͘͞Μ͋Δ w "SSBZTFMFDUWT0CKFDUTFMFDU w )BTIΛฦ͢IBTIΛఆٛͨ͜͠ͱ͕ͳ͍ਓ
  29. "SSBZJTB0CKFDU w 0CKFDUʹରͯ͠ಈ͘ϓϩάϥϜ͸"SSBZʹରͯ͠΋ಈ͘ʁʁ class Object def use_select select [STDIN], [],

    [] end end "".use_select # OK [1,2,3].use_select # ????
  30. 4PGU5ZQJOH͔ΒಘΒΕͨ஌ݟ w ࿦จͰ͸੒ޭ͍ͯ͠ΔΑ͏ʹݟ͑Δ͕࣮༻Ϩϕϧͷ΋ͷ͸ͳ͍ w ඞཁͦ͏ͳܕγεςϜͷػೳ͸Θ͔͖ͬͯͨ w Ή͠ΖܕΛॻ͍ͨํ͕ྑ͍ͷͰ͸ʁʁ w ϓϩάϥϚͷҙਤΛܕͰදݱ͢Δ w

    ҙਤͱҰக͠ͳ͍ίʔυΛݕग़͢Δ
  31. (SBEVBM5ZQJOH w ઴ਐతܕ෇͚ w ܕͳ͠ͷίʔυͱܕ͖ͭͷίʔυΛࠞͥΔ w ͩΜͩΜܕΛ෇͚͍ͯ͘ w ܕ͸ॻ͘

  32. ܕͳ͠ݴޠͷͨΊͷܕ w ͦΕͳΓʹڧྗͳܕγεςϜ w 6OJPOUZQFT qPXTFOTJUJWFUZQJOH HFOFSJDT  w μοΫλΠϐϯά

    w ߏ଄త෦෼ܕ w Ϋϥεͷܧঝؔ܎Λ͋ͱͰมߋͰ͖Δ࢓૊Έ )BTLFMM 4XJGU $  w (SBEVBM5ZQJOH
  33. Ξ΢τϥΠϯ w 3VCZͷ࿩ w ܕͳ͠ݴޠͷͨΊͷܕ w 5ZQF4DSJQUͱ࠷ۙͷྲྀΕ w 3VCZͷͨΊͷܕ

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

    1)1
  35. 5ZQF4DSJQU w ೥ݱࡏͰҰ൪উ͍ͬͯΔܕ͖ͭํݴ w λʔήοτݴޠ͸+4ʢϥϯλΠϜ΋+4ʣ class Drawer<ClothingType> { contents: ClothingType[]

    = []; add(object: ClothingType) { this.contents.push(object); } } interface Sock { color: string } interface TShirt { size: "s" | "m" | "l" } const drawer: Drawer<Sock> = new Drawer() drawer.push({ color: "white" }) drawer.push({ size: "s" })
  36. 5ZQF4DSJQUͷ͍͢͝ͱ͜Ζ w ܕͳ͠ݴޠʹܕΛ෇͚Δਓྨͷເ͕׎ͬͨ w ΈΜͳܕΛॻ͍͍ͯΔͷ͕͍͢͝ w ߏ଄తͳܕ͚ͩͰͳΜͱ͔ͳͬͯΔͷ͕͍͢͝ w 6OJPOUZQFTͱ͔qPXTFOTJUJWFUZQFTͱ͔MPHJDBMUZQFTͱ͔͠Εͬͱ ೖͬͯΔͷ͕͍͢͝

    w ϥϯλΠϜͱͷ੍໿Λ৐Γӽ͑ͯಈ͍ͯΔͷ͕͍͢͝
  37. ܕ͸ॻ͔ͳͯ͘͸͍͚ͳ͍ w ΑͬΆͲࣗ໌ͳ΋ͷҎ֎͸ॻ͘ w ϥΠϒϥϦͷܕ͸EFpOJUFMZUZQFEʹू·͍ͬͯΔ const numbers: number[] = [1,2,3]

    numbers.map<string>(x => x.toString())
  38. jQuery.d.ts

  39. ߏ଄తͳܕ w Ϋϥεͷܧঝؔ܎Ͱ͸ͳ͘ɺϝιουͷू߹Ͱ෦෼ܕؔ܎Λ൑ఆ͢Δ w ߏ଄తͳܕ͚ͩͱ͍͏ͷ͸௝͍͠ w ໰୊͸͋Δ interface ForEach<A> {

    forEach: (fun: (a: A) => void) => void } const x: ForEach<number> = [1,2,3]
  40. ͨ·ͨ·ಉ͡ߏ଄͕͋ͬͨΒʁ w 5γϟπͱζϘϯ͕۠ผͰ͖ͳ͘ͳΔ w #SBOEFEUZQFͰରԠ͢Δ interface TShirt { size: "s"

    | "m" | "l"; } interface Pants { size: "s" | "m" | "l"; }
  41. ͨ·ͨ·ಉ͡ߏ଄͕͋ͬͨΒʁ 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"; }
  42. 6OJPO5ZQFT'MPXTFOTJUJWF5ZQJOH w OVMMVOEFpOFEͱ͏·͘΍ΕΔΑ͏ʹͳͬͨ const x: string | undefined = ...

    // Object is possibly 'undefined'. x.toUpperCase() if (x) { x.toUpperCase() }
  43. ϥϯλΠϜͷ੍໿ w +4ͷϥϯλΠϜʹͰ͖ͳ͍͜ͱ͸54Ͱ΋Ͱ͖ͳ͍ w ʮ͋Δ஋͕ΠϯλʔϑΣʔεʹద߹͍ͯ͠Δ͔ݕ͍ࠪͨ͠ʯ w Ϣʔβʔ͕ࣗ෼ͷ੹೚Ͱݕূ͢Δ -PHJDBMUZQFT  •

    function isPants(object: any): object is Pants {
 return object.type == "pants"
 }
  44. ஌ݟ w ਓؒ͸ܕΛॻ͘ w ʢܕΛॻ͖ͨ͘ͳ͍ਓ͸5ZQF4DSJQUΛ࢖Θͳ͍ͷͰ؍ଌͰ͖ͳ͍ʣ w େମ+BWB4DSJQUͷίʔυʹܕ͕ͭ͘ w 6OJPOUZQFTͱ͔qPXTFOTJUJWFUZQJOHͱ͔͕ॏཁ w

    ߏ଄త෦෼ܕ΋ಈ͘ w ϥϯλΠϜͷ੍ݶΛ৐Γӽ͑ΔͨΊ޻෉ JTܕ
  45. 1ZUIPO 1)1 w ϝιουͷܕΛॻ͘ه๏͕ಋೖ͞Εͨ w ܕݕࠪ͸࣮ߦ࣌ w ϝιουݺͼग़͠ͷͱ͖ʹܕݕࠪ͢Δ w ੩తͳܕݕࠪث΋։ൃ͞Ε͍ͯΔ

    function sum(int $a, int $b) { return $a + $b; }
  46. Ξ΢τϥΠϯ w 3VCZͷ࿩ w ܕͳ͠ݴޠͷͨΊͷܕ w 5ZQF4DSJQUͱ࠷ۙͷྲྀΕ w 3VCZͷͨΊͷܕ

  47. 3VCZͷͨΊͷܕ w 4PGUUZQJOHͷ஌ݟˠਪ࿦ΛؤுΔͷ͸௅ઓతʢ!NBNFʣ w 5ZQF4DSJQUͷ஌ݟ w ਓྨ͸ܕΛॻ͘ w ͦΕͳΓʹڧྗͳܕγεςϜ͕͋Ε͹্ख͘΍Εͦ͏ w

    1ZUIPO 1)1ͷ஌ݟ w ܕ஫ऍ͸ܾΊͳ͍ͱ͍͚ͳ͍ w ܕݕࠪث͸ผπʔϧʹ͢Δ
  48. ܕ஫ऍͷه๏ 3#4 w গͳ͘ͱ΋ϥΠϒϥϦͷܕΛॻ͘ํ๏͕ඞཁ w ܕݕࠪπʔϧ͕ͦΕͧΕʹ༻ҙ͢Δͷ͸͔ͳΓݫ͍͠ w ϥϯλΠϜͷݕ͕ࠪͰ͖Δ͚ͩͰ΋ͦΕͳΓʹخ͍͠Ͱ͸ʁ w ιʔείʔυʹຒΊࠐΉߏจ͸࠾༻͠ͳ͍

  49. ૊ΈࠐΈͷܕ஫ऍߏจʢෆ࠾༻ʣ 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
  50. ͦΕͳΓʹϦονͳܕ w λϓϧɺϨίʔυ
 [Integer, Symbol] w Ϧςϥϧܕ
 1, "hello", :world

    w 6OJPOUZQFT
 Integer | String w 0QUJPOBMUZQFTɺ(FOFSJDTʜ
 Array[String]? w յΕ͍ͯΔ΋ͷ͸JODPNQBUJCMF
 incompatible
 def select: [A] () { (Elem) -> A
  51. μοΫλΠϐϯά w JOUFSGBDFΛఆٛͯ͠ɺཁٻ͞ΕΔϝιουͷू߹Λॻ͘ w ϝιου͕͋Δ͔ͳ͍͔Ͱݕࠪ͞ΕΔ interface _Push def <<: (String)

    -> void end def foo: (_Push) -> void def foo(a) a << "hello" end foo [] foo "" foo 3 # Τϥʔ
  52. ࣮ߦ࣌ݕ͚ࠪͩͰ΋ 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
  53. IUUQTHJUIVCDPNTJEFSHPPEDIFDLUSFFSCT

  54. ·ͱΊ w 4PGUUZQJOHΈ͍ͨʹਪ࿦ΛؤுΔͷ͸߹ཧతͰ͸ͳ͍ w ܕΛॻ͔ͳ͍ͷ͸ݫ͍͠ w ਓؒ͸ܕΛॻ͘ʢ͜͜೥ͰಘΒΕͨ஌ݟʣ w 3VCZͷͨΊͷܕ w

    ΘΓͱϦονͳܕ(FOFSJDTɺ6OJPOUZQFTɺ'MPXTFOTJUJWFUZQJOH w μοΫλΠϐϯά͸ؤுΔʢߏ଄త෦෼ܕʣ
  55. 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