Share
Embed
仮想関数テーブルと型クラスを見比べる
型クラスについての理解を深めるために、仮想関数テーブルで部分型多相+動的ディスパッチを実現した場合との違い・共通点を見比べてみます。型クラスは(その出自はともかく)関数型プログラミング特有の概念というわけではないことを確かめます。
INA Lintaro
January 26, 2024
Transcript
43 slides
-
ࣗݾհ ໊લ ɹ ͍ ͳ ҏಸ ɹ ɹ ΓΜͨΖ͏ ྛଠ
ɹ ( id:tarao @tarao @oarat) 2021-02 ∼ ͯͳ ΤϯδχΞϦϯάϚωʔδϟ 2013-04 ∼ ͯͳ ΤϯδχΞ 2010-04 ∼ ژେֶ ใֶݚڀՊ (ࠤ౻ɾޒेཛྷݚ) ത࢜ޙظ՝ఔ / ຊֶज़ৼڵձ ಛผݚڀһ (DC1) ࠷ۙ ▶ record4s: extensible records for Scala ▶ ͋ΒΏΔϓϩάϥϛϯάݴޠͷ࠷ઌΛߦ ͘ Scala 3 ͷϚΫϩ ੲ ▶ L. Ina and A. Igarashi. Gradual Typing for Generics. In Proc. of OOPSLA 2011. ▶ “gradual typing” Λʮਐతܕ͚ʯͱ༁ ͨ͠ऀͷ 1 ਓ -
ܕΫϥεͱOOP SPJ ᐌ͘ “ ▶ A bit like OOP, except
that method suite passed separately? ▶ No!! Type classes implement type-based dispatch, not value-based dispatch ▶ S. P. Jones. Classes, Jim, but not as we know them — Type classes in Haskell. In ECOOP 2009. -
͋ʔ ͦʔΏʔ͜ͱͶ શʹཧղͨ͠ . . . ͬͯࢥͬͨͷ tarao ͚͔ͩ͠Εͳ͍͔Β ͜ͷΛ͢Δ͜ͱʹ͠·ͨ͠
(tarao ʹͱͬͯͨΓલͷ͔͠͠·ͤΜ) -
ݴޠػೳͷҙຯ ݴޠ L ͷػೳ F ▶ L ⇝ (L −
F) ͷมͰఆٛ͢Δ (࣮ࡍͷॲཧܥʹ͓͚Δҥߏจͷ desugar ʹ૬) ྫ ▶ ݴޠ L : Haskell ▶ ػೳ F : ܕΫϥε ▶ ม : ܕΫϥε͋Γͷ Haskell ⇝ ܕΫϥεͳ͠ͷ Haskell (Wadler ’89 ͷจͰ࣮ࡍͦ͏ͬͯҙຯΛ༩͍͑ͯΔ) -
OOP (෦ܕଟ૬ + ಈతσΟεύον) abstract class Pet: def speak(): String
class Cat extends Pet: override def speak(): String = "Meow" class Dog extends Pet: override def speak(): String = "Woof" def listen(pet: Pet): String = pet.speak() listen(new Cat) // "Meow" listen(new Dog) // "Woof" -
OOP (෦ܕଟ૬ + ಈతσΟεύον) abstract class Pet: def speak(): String
class Cat extends Pet: override def speak(): String = "Meow" class Dog extends Pet: override def speak(): String = "Woof" def listen(pet: Pet): String = pet.speak() listen(new Cat) // "Meow" listen(new Dog) // "Woof" ▶ ҟͳΔܕΛ౷Ұతʹѻ͍͍ͨ -
OOP (෦ܕଟ૬ + ಈతσΟεύον) abstract class Pet: def speak(): String
class Cat extends Pet: override def speak(): String = "Meow" class Dog extends Pet: override def speak(): String = "Woof" def listen(pet: Pet): String = pet.speak() listen(new Cat) // "Meow" listen(new Dog) // "Woof" ▶ ڞ௨ͷ্ҐܕΛࢦఆ (෦ܕଟ૬) -
OOP (෦ܕଟ૬ + ಈతσΟεύον) abstract class Pet: def speak(): String
class Cat extends Pet: override def speak(): String = "Meow" class Dog extends Pet: override def speak(): String = "Woof" def listen(pet: Pet): String = pet.speak() listen(new Cat) // "Meow" listen(new Dog) // "Woof" ▶ ಉ໊ϝιουΛ෦ܕ͝ͱʹ࣮ -
OOP (෦ܕଟ૬ + ಈతσΟεύον) abstract class Pet: def speak(): String
class Cat extends Pet: override def speak(): String = "Meow" class Dog extends Pet: override def speak(): String = "Woof" def listen(pet: Pet): String = pet.speak() listen(new Cat) // "Meow" listen(new Dog) // "Woof" ▶ ݺΕΔͷ෦ܕͷϝιου࣮ (ಈతσΟεύον) -
OOPͷҙຯ (Ծؔςʔϒϧ (vtable)) abstract class Pet: def speak(): String class
Cat extends Pet: override def speak(): String = "Meow" class Dog extends Pet: override def speak(): String = "Woof" def listen(pet: Pet): String = pet.speak() abstract class Pet( val vtable: PetMethods ) class PetMethods(val speak: Pet => String) class Cat extends Pet( CatIsPet ): def speak(): String = "Meow" val CatIsPet = PetMethods((pet: Pet) => pet.asInstanceOf[Cat].speak() ) class Dog extends Pet( DogIsPet ): def speak(): String = "Woof" val DogIsPet = PetMethods((pet: Pet) => pet.asInstanceOf[Dog].speak() ) def listen(pet: Pet): String = pet.vtable .speak(pet) ˞ ࣮ࡍͷॲཧܥͷ࣮ͱҟͳΔ (͋͘·Ͱ֓೦্ͷઆ໌) -
OOPͷҙຯ (Ծؔςʔϒϧ (vtable)) abstract class Pet: def speak(): String class
Cat extends Pet: override def speak(): String = "Meow" class Dog extends Pet: override def speak(): String = "Woof" def listen(pet: Pet): String = pet.speak() abstract class Pet( val vtable: PetMethods ) class PetMethods(val speak: Pet => String) class Cat extends Pet( CatIsPet ): def speak(): String = "Meow" val CatIsPet = PetMethods((pet: Pet) => pet.asInstanceOf[Cat].speak() ) class Dog extends Pet( DogIsPet ): def speak(): String = "Woof" val DogIsPet = PetMethods((pet: Pet) => pet.asInstanceOf[Dog].speak() ) def listen(pet: Pet): String = pet.vtable .speak(pet) ▶ override ͳ͠Ͱॻ͘ -
OOPͷҙຯ (Ծؔςʔϒϧ (vtable)) abstract class Pet: def speak(): String class
Cat extends Pet: override def speak(): String = "Meow" class Dog extends Pet: override def speak(): String = "Woof" def listen(pet: Pet): String = pet.speak() abstract class Pet( val vtable: PetMethods ) class PetMethods(val speak: Pet => String) class Cat extends Pet( CatIsPet ): def speak(): String = "Meow" val CatIsPet = PetMethods((pet: Pet) => pet.asInstanceOf[Cat].speak() ) class Dog extends Pet( DogIsPet ): def speak(): String = "Woof" val DogIsPet = PetMethods((pet: Pet) => pet.asInstanceOf[Dog].speak() ) def listen(pet: Pet): String = pet.vtable .speak(pet) ▶ ڞ௨ͷϝιουͷശ (ࣙॻ) Λ༻ҙ͓ͯ͘͠ -
OOPͷҙຯ (Ծؔςʔϒϧ (vtable)) abstract class Pet: def speak(): String class
Cat extends Pet: override def speak(): String = "Meow" class Dog extends Pet: override def speak(): String = "Woof" def listen(pet: Pet): String = pet.speak() abstract class Pet( val vtable: PetMethods ) class PetMethods(val speak: Pet => String) class Cat extends Pet( CatIsPet ): def speak(): String = "Meow" val CatIsPet = PetMethods((pet: Pet) => pet.asInstanceOf[Cat].speak() ) class Dog extends Pet( DogIsPet ): def speak(): String = "Woof" val DogIsPet = PetMethods((pet: Pet) => pet.asInstanceOf[Dog].speak() ) def listen(pet: Pet): String = pet.vtable .speak(pet) ▶ ෦ܕ͝ͱʹผʑͷϝιουΛ٧Ί͓ͯ͘ -
OOPͷҙຯ (Ծؔςʔϒϧ (vtable)) abstract class Pet: def speak(): String class
Cat extends Pet: override def speak(): String = "Meow" class Dog extends Pet: override def speak(): String = "Woof" def listen(pet: Pet): String = pet.speak() abstract class Pet( val vtable: PetMethods ) class PetMethods(val speak: Pet => String) class Cat extends Pet( CatIsPet ): def speak(): String = "Meow" val CatIsPet = PetMethods((pet: Pet) => pet.asInstanceOf[Cat].speak() ) class Dog extends Pet( DogIsPet ): def speak(): String = "Woof" val DogIsPet = PetMethods((pet: Pet) => pet.asInstanceOf[Dog].speak() ) def listen(pet: Pet): String = pet.vtable .speak(pet) ▶ vtable Λܦ༝ͯ͠ϝιουΛݺͿ -
ܕΫϥε (ύϥϝʔλଟ૬ + ΞυϗοΫଟ૬) trait Pet[P] : extension (p: P)
def speak(): String class Cat: def speak(): String = "Meow" given Pet[Cat] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[Dog] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet ](pet: P ): String = pet.speak() listen( new Cat ) // "Meow" listen( new Dog ) // "Woof" -
ܕΫϥε (ύϥϝʔλଟ૬ + ΞυϗοΫଟ૬) trait Pet[P] : extension (p: P)
def speak(): String class Cat: def speak(): String = "Meow" given Pet[Cat] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[Dog] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet ](pet: P ): String = pet.speak() listen( new Cat ) // "Meow" listen( new Dog ) // "Woof" ▶ ҟͳΔܕΛ౷Ұతʹѻ͍͍ͨ -
ܕΫϥε (ύϥϝʔλଟ૬ + ΞυϗοΫଟ૬) trait Pet[P] : extension (p: P)
def speak(): String class Cat: def speak(): String = "Meow" given Pet[Cat] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[Dog] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet ](pet: P ): String = pet.speak() listen( new Cat ) // "Meow" listen( new Dog ) // "Woof" ▶ ಛఆͷΠϯλϑΣʔεΛཁٻ (͜Ε͕ܕΫϥε) -
ܕΫϥε (ύϥϝʔλଟ૬ + ΞυϗοΫଟ૬) trait Pet[P] : extension (p: P)
def speak(): String class Cat: def speak(): String = "Meow" given Pet[Cat] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[Dog] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet ](pet: P ): String = pet.speak() listen( new Cat ) // "Meow" listen( new Dog ) // "Woof" ▶ ΠϯλϑΣʔεΛຬͨ͢ূڌ (ܕΫϥεͷΠϯελϯε) -
ܕΫϥε (ύϥϝʔλଟ૬ + ΞυϗοΫଟ૬) trait Pet[P] : extension (p: P)
def speak(): String class Cat: def speak(): String = "Meow" given Pet[Cat] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[Dog] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet ](pet: P ): String = pet.speak() listen( new Cat ) // "Meow" listen( new Dog ) // "Woof" ▶ ূڌʹج͍ͮͯݺͼ͚ -
ܕΫϥεͷҙຯ trait Pet[P]: extension (p: P) def speak(): String class
Cat: def speak(): String = "Meow" given Pet[Cat] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[Dog] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet](pet: P): String = pet.speak() class Pet[P](val speak: P => String) class Cat: def speak(): String = "Meow" val CatIsPet = Pet[Cat]((cat: Cat) => cat.speak()) class Dog: def speak(): String = "Woof" val DogIsPet = Pet[Dog]((dog: Dog) => dog.speak()) def listen[P](pet: P) (dict: Pet[P]) : String = dict .speak(pet) -
ܕΫϥεͷҙຯ trait Pet[P]: extension (p: P) def speak(): String class
Cat: def speak(): String = "Meow" given Pet[Cat] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[Dog] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet](pet: P): String = pet.speak() class Pet[P](val speak: P => String) class Cat: def speak(): String = "Meow" val CatIsPet = Pet[Cat]((cat: Cat) => cat.speak()) class Dog: def speak(): String = "Woof" val DogIsPet = Pet[Dog]((dog: Dog) => dog.speak()) def listen[P](pet: P) (dict: Pet[P]) : String = dict .speak(pet) ▶ ܕΫϥεͷ࣮ମϝιουͷࣙॻ -
ܕΫϥεͷҙຯ trait Pet[P]: extension (p: P) def speak(): String class
Cat: def speak(): String = "Meow" given Pet[Cat] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[Dog] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet](pet: P): String = pet.speak() class Pet[P](val speak: P => String) class Cat: def speak(): String = "Meow" val CatIsPet = Pet[Cat]((cat: Cat) => cat.speak()) class Dog: def speak(): String = "Woof" val DogIsPet = Pet[Dog]((dog: Dog) => dog.speak()) def listen[P](pet: P) (dict: Pet[P]) : String = dict .speak(pet) ▶ ΠϯλϑΣʔεͷূڌࣙॻΠϯελϯε -
ܕΫϥεͷҙຯ trait Pet[P]: extension (p: P) def speak(): String class
Cat: def speak(): String = "Meow" given Pet[Cat] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[Dog] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet](pet: P): String = pet.speak() class Pet[P](val speak: P => String) class Cat: def speak(): String = "Meow" val CatIsPet = Pet[Cat]((cat: Cat) => cat.speak()) class Dog: def speak(): String = "Woof" val DogIsPet = Pet[Dog]((dog: Dog) => dog.speak()) def listen[P](pet: P) (dict: Pet[P]) : String = dict .speak(pet) ▶ ܕΫϥεΛ͏ϝιουࣙॻΛऔΔܗʹม -
ܕΫϥεͷҙຯ trait Pet[P]: extension (p: P) def speak(): String class
Cat: def speak(): String = "Meow" given Pet[Cat] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[Dog] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet](pet: P): String = pet.speak() listen(new Cat) listen(new Dog) class Pet[P](val speak: P => String) class Cat: def speak(): String = "Meow" val CatIsPet = Pet[Cat]((cat: Cat) => cat.speak()) class Dog: def speak(): String = "Woof" val DogIsPet = Pet[Dog]((dog: Dog) => dog.speak()) def listen[P](pet: P) (dict: Pet[P]) : String = dict .speak(pet) listen(new Cat) (CatIsPet) listen(new Dog) (DogIsPet) -
දΛݟൺΔ OOP abstract class Pet : def speak(): String class
Cat extends Pet : override def speak(): String = "Meow" class Dog extends Pet : override def speak(): String = "Woof" def listen(pet: Pet ): String = pet.speak() ܕΫϥε trait Pet[ P ]: extension (p: P ) def speak(): String class Cat: def speak(): String = "Meow" given Pet[ Cat ] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[ Dog ] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet](pet: P ): String = pet.speak() -
දΛݟൺΔ OOP abstract class Pet : def speak(): String class
Cat extends Pet : override def speak(): String = "Meow" class Dog extends Pet : override def speak(): String = "Woof" def listen(pet: Pet ): String = pet.speak() ܕΫϥε trait Pet[ P ]: extension (p: P ) def speak(): String class Cat: def speak(): String = "Meow" given Pet[ Cat ] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[ Dog ] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet](pet: P ): String = pet.speak() ▶ ෦ܕଟ૬ vs. ύϥϝʔλଟ૬ -
දΛݟൺΔ OOP abstract class Pet : def speak(): String class
Cat extends Pet : override def speak(): String = "Meow" class Dog extends Pet : override def speak(): String = "Woof" def listen(pet: Pet ): String = pet.speak() ܕΫϥε trait Pet[ P ]: extension (p: P ) def speak(): String class Cat: def speak(): String = "Meow" given Pet[ Cat ] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[ Dog ] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet](pet: P ): String = pet.speak() ▶ ͕ؔܕͷఆٛͱີ݁߹ vs. ͕ؔޙ͚ -
දΛݟൺΔ OOP abstract class Pet : def speak(): String class
Cat extends Pet : override def speak(): String = "Meow" class Dog extends Pet : override def speak(): String = "Woof" def listen(pet: Pet ): String = pet.speak() ܕΫϥε trait Pet[ P ]: extension (p: P ) def speak(): String class Cat: def speak(): String = "Meow" given Pet[ Cat ] with extension (cat: Cat) def speak(): String = cat.speak() class Dog: def speak(): String = "Woof" given Pet[ Dog ] with extension (dog: Dog) def speak(): String = dog.speak() def listen[P: Pet](pet: P ): String = pet.speak() ▶ ಉ໊ͰΦʔόʔϥΠυ vs. όϥόϥʹ࣮ (ผ໊ͰՄ) -
ҙຯΛݟൺΔ OOP abstract class Pet ( val vtable: PetMethods )
class PetMethods (val speak: Pet => String) class Cat extends Pet(CatIsPet) : def speak(): String = "Meow" val CatIsPet = PetMethods ((pet: Pet ) => pet .asInstanceOf[Cat] .speak()) class Dog extends Pet(DogIsPet) : def speak(): String = "Woof" val DogIsPet = PetMethods ((pet: Pet ) => pet .asInstanceOf[Dog] .speak()) def listen(pet: Pet ): String = pet.vtable .speak(pet) ܕΫϥε class Pet[P] (val speak: P => String) class Cat: def speak(): String = "Meow" val CatIsPet = Pet[Cat] ((cat: Cat ) => cat.speak()) class Dog: def speak(): String = "Woof" val DogIsPet = Pet[Dog] ((dog: Dog ) => dog.speak()) def listen [P] (pet: P ) (dict: Pet[P]) : String = dict .speak(pet) -
ҙຯΛݟൺΔ OOP abstract class Pet ( val vtable: PetMethods )
class PetMethods (val speak: Pet => String) class Cat extends Pet(CatIsPet) : def speak(): String = "Meow" val CatIsPet = PetMethods ((pet: Pet ) => pet .asInstanceOf[Cat] .speak()) class Dog extends Pet(DogIsPet) : def speak(): String = "Woof" val DogIsPet = PetMethods ((pet: Pet ) => pet .asInstanceOf[Dog] .speak()) def listen(pet: Pet ): String = pet.vtable .speak(pet) ܕΫϥε class Pet[P] (val speak: P => String) class Cat: def speak(): String = "Meow" val CatIsPet = Pet[Cat] ((cat: Cat ) => cat.speak()) class Dog: def speak(): String = "Woof" val DogIsPet = Pet[Dog] ((dog: Dog ) => dog.speak()) def listen [P] (pet: P ) (dict: Pet[P]) : String = dict .speak(pet) ▶ ෦ܕଟ૬ vs. ύϥϝʔλଟ૬ -
ҙຯΛݟൺΔ OOP abstract class Pet ( val vtable: PetMethods )
class PetMethods (val speak: Pet => String) class Cat extends Pet(CatIsPet) : def speak(): String = "Meow" val CatIsPet = PetMethods ((pet: Pet ) => pet .asInstanceOf[Cat] .speak()) class Dog extends Pet(DogIsPet) : def speak(): String = "Woof" val DogIsPet = PetMethods ((pet: Pet ) => pet .asInstanceOf[Dog] .speak()) def listen(pet: Pet ): String = pet.vtable .speak(pet) ܕΫϥε class Pet[P] (val speak: P => String) class Cat: def speak(): String = "Meow" val CatIsPet = Pet[Cat] ((cat: Cat ) => cat.speak()) class Dog: def speak(): String = "Woof" val DogIsPet = Pet[Dog] ((dog: Dog ) => dog.speak()) def listen [P] (pet: P ) (dict: Pet[P]) : String = dict .speak(pet) ▶ ໊લ͕ҧ͏͚ͩ -
ҙຯΛݟൺΔ OOP abstract class Pet ( val vtable: PetMethods )
class PetMethods (val speak: Pet => String) class Cat extends Pet(CatIsPet) : def speak(): String = "Meow" val CatIsPet = PetMethods ((pet: Pet ) => pet .asInstanceOf[Cat] .speak()) class Dog extends Pet(DogIsPet) : def speak(): String = "Woof" val DogIsPet = PetMethods ((pet: Pet ) => pet .asInstanceOf[Dog] .speak()) def listen(pet: Pet ): String = pet.vtable .speak(pet) ܕΫϥε class Pet[P] (val speak: P => String) class Cat: def speak(): String = "Meow" val CatIsPet = Pet[Cat] ((cat: Cat ) => cat.speak()) class Dog: def speak(): String = "Woof" val DogIsPet = Pet[Dog] ((dog: Dog ) => dog.speak()) def listen [P] (pet: P ) (dict: Pet[P]) : String = dict .speak(pet) ▶ ͔ΒऔΓग़͢ vs. ҾͰ͢ -
ҙຯΛݟൺΔ OOP abstract class Pet ( val vtable: PetMethods )
class PetMethods (val speak: Pet => String) class Cat extends Pet(CatIsPet) : def speak(): String = "Meow" val CatIsPet = PetMethods ((pet: Pet ) => pet .asInstanceOf[Cat] .speak()) class Dog extends Pet(DogIsPet) : def speak(): String = "Woof" val DogIsPet = PetMethods ((pet: Pet ) => pet .asInstanceOf[Dog] .speak()) def listen(pet: Pet ): String = pet.vtable .speak(pet) ܕΫϥε class Pet[P] (val speak: P => String) class Cat: def speak(): String = "Meow" val CatIsPet = Pet[Cat] ((cat: Cat ) => cat.speak()) class Dog: def speak(): String = "Woof" val DogIsPet = Pet[Dog] ((dog: Dog ) => dog.speak()) def listen [P] (pet: P ) (dict: Pet[P]) : String = dict .speak(pet) ▶ ͋ͱಉ͡!! -
ҧ͏ͱ͜Ζ OOP ܕΫϥε ଟ૬ ෦ܕଟ૬ ύϥϝʔλଟ૬ ܕͷؔ ີ݁߹ ޙ͚Մ ˞
ϝιου࣮ ಉ໊ͰΦʔόʔϥΠυ ໌ࣔతʹࢦఆ ࣙॻͷ͠ํ ʹೖΕΔ ҾͰ͢ ࣙॻͷղܾ ಈత ੩త ˞ ͜ͷͨΊʹܕΫϥεͷΠϯελϯεղܾͷΈ͕ඞཁ ▶ ཧܕϓϩάϥϛϯάΈ͍ͨʹͳΔ