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

Intro to typeclass in Scala

Intro to typeclass in Scala

Kazuhiro Ichikawa

June 28, 2019
Tweet

More Decks by Kazuhiro Ichikawa

Other Decks in Technology

Transcript

  1. ܕΫϥε 5ZQFDMBTT w -BOHVBHFDPOTUSVDUUIBUTVQQPSUTBEIPDQPMZNPSQIJTN w "EIPDQPMZNPSQIJTN  w "LJOEPGQPMZNPSQIJTNUIBUBMMPXTEFDMBSJOHGVODUJPOTUIBU DBOCFBQQMJFEGPSBSHVNFOUTPGEJGGFSFOUUZQFT

    w *UJTLOPXOBTPWFSMPBEJOH w 0,4P 8IBUJTUZQFDMBTT ܕΫϥεͬͯԿ ΞυϗοΫϙϦϞʔϑΟζϜͬͯԿ  Φʔόʔϩʔυ ݁ہͲ͏͍͏͜ͱ
  2. ۩ମྫίϯύϨʔλ &YBNQMF$PNQBSBUPS Α͘ར༻͞ΕΔ۩ମྫ͸$PNQBSBUPSͰɺ
 TPSU಺෦Ͱར༻͢Δൺֱؔ਺Λ֎͔Βม͑ΒΕΔ interface/trait Comparator[T] abstract compare(a: T, b:

    T) object DateComparator def compare
 (a: Date, b: Date) object IntComparator def compare
 (a: Int, b: Int) def sort[T]
 (list:List[T])
 (cmp:Comparator[T]) = { … cmp.compare(…) … } … sort(list, 
 IntComparator) … DBMM
  3. ۩ମྫίϯύϨʔλ &YBNQMF$PNQBSBUPS 4DBMBͰͷ࣮૷ྫ trait Comparator[T] { def compare(a: T, b:

    T): Int } object IntComparator extends Comparator[Int] { def compare(a: Int, b: Int): Int = a - b } def sort[T](list: List[T], comparator: Comparator[T]): List[T] = { list match { case x :: xs => val (ys, zs) = xs.partition(a => comparator.compare(x, a) > 0) sort(ys, comparator) ++ List(x) ++ sort(zs, comparator) case Nil => Nil } } sort(List(6, 1, 4, 7, 5, 2, 9, 3, 8), IntComparator)
  4. ετϥςδ͸େ఍ͷ৔߹ࣗ໌Ͱ͋Δ 4USBUFHZJTPCWJPVTJONPTUDBTFT w *ONPTUDBTFT XFVTFlOBUVSBMzPSEFSGPSDPNQBSJOHWBMVFT w OVNFSJDBMPSEFSGPSJOUFHFSWBMVFT w DISPOPMPHJDBMPSEFSGPSEBUFWBMVFT w

    /PUFUIBUlOBUVSBMzPSEFSJTEJGGFSFOUCFUXFFOEJGGFSFOUUZQFT w 0CWJPVTTUSBUFHZDBOCFJOGFSSFEGSPNTUBUJDUZQF ܕʹΑͬͯzࣗવͳzετϥςδ͕͋Γɺ
 େ఍͸ͦΕΛ࢖͑͹ྑ͍
  5. ܕΫϥεͱܕΫϥεΠϯελϯε 5ZQFDMBTTBOEUZQFDMBTTJOTUBODF ͭ·Γ interface/trait Comparator[T] abstract compare(a: T, b: T)

    object DateComparator def compare
 (a: Date, b: Date) object IntComparator def compare
 (a: Int, b: Int) def sort[T]
 (list:List[T])
 (cmp:Comparator[T]) = { … cmp.compare(…) … } DBMM … sort(list, 
 IntComparator) …
  6. ܕΫϥεͱܕΫϥεΠϯελϯε 5ZQFDMBTTBOEUZQFDMBTTJOTUBODF ͕͜͜ܕΫϥε interface/trait Comparator[T] abstract compare(a: T, b: T)

    object DateComparator def compare
 (a: Date, b: Date) object IntComparator def compare
 (a: Int, b: Int) def sort[T]
 (list:List[T])
 (cmp:Comparator[T]) = { … cmp.compare(…) … } DBMM 5ZQFDMBTT … sort(list, 
 IntComparator) …
  7. ܕΫϥεͱܕΫϥεΠϯελϯε 5ZQFDMBTTBOEUZQFDMBTTJOTUBODF *OU$PNQBSBUPS͸$PNQBSBUPS<*OU>Λ࣮૷͍ͯ͠ΔͷͰ interface/trait Comparator[T] abstract compare(a: T, b: T)

    object DateComparator def compare
 (a: Date, b: Date) object IntComparator def compare
 (a: Int, b: Int) def sort[T]
 (list:List[T])
 (cmp:Comparator[T]) = { … cmp.compare(…) … } DBMM $PNQBSBUPS<*OU> 5ZQFDMBTT … sort(list, 
 IntComparator) …
  8. ܕΫϥεͱܕΫϥεΠϯελϯε 5ZQFDMBTTBOEUZQFDMBTTJOTUBODF *OU͸ܕΫϥε$PNQBSBUPSͷΠϯελϯεͰ͋Δͱ͍͏ interface/trait Comparator[T] abstract compare(a: T, b: T)

    object DateComparator def compare
 (a: Date, b: Date) object IntComparator def compare
 (a: Int, b: Int) def sort[T]
 (list:List[T])
 (cmp:Comparator[T]) = { … cmp.compare(…) … } DBMM 5ZQFDMBTT *OUJTJOTUBODFPG $PNQBSBUPS $PNQBSBUPS<*OU> … sort(list, 
 IntComparator) …
  9. ܕΫϥε੍໿ 5ZQFDMBTTDPOTUSBJOU ͭ·Γ interface/trait Comparator[T] abstract compare(a: T, b: T)

    object DateComparator def compare
 (a: Date, b: Date) object IntComparator def compare
 (a: Int, b: Int) def sort[T]
 (list:List[T])
 (cmp:Comparator[T]) = { … cmp.compare(…) … } DBMM 5ZQFDMBTT *OUJTJOTUBODFPG $PNQBSBUPS $PNQBSBUPS<*OU> … sort(list, 
 IntComparator) …
  10. ܕΫϥε੍໿ 5ZQFDMBTTDPOTUSBJOU TPSUͷ$PNQBSBUPS<5>ܕͷҾ਺͸ܕΫϥε੍໿ interface/trait Comparator[T] abstract compare(a: T, b: T)

    object DateComparator def compare
 (a: Date, b: Date) object IntComparator def compare
 (a: Int, b: Int) def sort[T]
 (list:List[T])
 (cmp:Comparator[T]) = { … cmp.compare(…) … } DBMM 5ZQFDMBTT 5ZQFDMBTTDPOTUSBJOU *OUJTJOTUBODFPG $PNQBSBUPS $PNQBSBUPS<*OU> … sort(list, 
 IntComparator) …
  11. ܕΫϥεͷΠϯελϯεએݴ 5ZQFDMBTTJOTUBODFEFDMBSBUJPO ͭ·Γ interface/trait Comparator[T] abstract compare(a: T, b: T)

    object DateComparator def compare
 (a: Date, b: Date) object IntComparator def compare
 (a: Int, b: Int) def sort[T]
 (list:List[T])
 (cmp:Comparator[T]) = { … cmp.compare(…) … } DBMM 5ZQFDMBTT 5ZQFDMBTTDPOTUSBJOU *OUJTJOTUBODFPG $PNQBSBUPS $PNQBSBUPS<*OU> … sort(list, 
 IntComparator) …
  12. ܕΫϥεͷΠϯελϯεએݴ 5ZQFDMBTTJOTUBODFEFDMBSBUJPO *OU$PNQBSBUPS͕$PNQBSBUPS<*OU>ͷzࣗવͳz࣮૷Ͱ͋ Δͱએݴ͢Δͱ Πϯελϯεએݴ interface/trait Comparator[T] abstract compare(a: T,

    b: T) object DateComparator def compare
 (a: Date, b: Date) object IntComparator def compare
 (a: Int, b: Int) def sort[T]
 (list:List[T])
 (cmp:Comparator[T]) = { … cmp.compare(…) … } DBMM 5ZQFDMBTT 5ZQFDMBTTDPOTUSBJOU %FDMBSFIntComparatorJTOBUVSBMTUSBUFHZ
 GPSComparator[Int] … sort(list, 
 IntComparator) …
  13. ܕΫϥεͷΠϯελϯεએݴ 5ZQFDMBTTJOTUBODFEFDMBSBUJPO TPSUͷҾ਺ʹετϥςδΛ༩͑ͳ͘ͱ΋ܕγεςϜ͕ࣗಈ Ͱ*OU$PNQBSBUPSΛ୳ͯ͠౉ͯ͘͠ΕΔ interface/trait Comparator[T] abstract compare(a: T, b:

    T) object DateComparator def compare
 (a: Date, b: Date) object IntComparator def compare
 (a: Int, b: Int) def sort[T]
 (list:List[T])
 (cmp:Comparator[T]) = { … cmp.compare(…) … } … sort(list) … DBMM 5ZQFDMBTT 5ZQFDMBTTDPOTUSBJOU 5ZQFTZTUFNBVUPNBUJDBMMZ SFTPMWFTUZQFDMBTT
  14. ܕΫϥε੍໿ 5ZQFDMBTTDPOTUSBJOU w *O4DBMB QBSBNFUFSXJUI“implicit”LFZXPSEFYQSFTTFT UZQFDMBTTDPOTUSBJOU w "SHVNFOUPGJNQMJDJUQBSBNFUFSJTBVUPNBUJDBMMZTFBSDIFE GSPNEFDMBSFEJNQMJDJUWBMVFTJOTDPQF ܕΫϥε੍໿͸JNQMJDJUύϥϝʔλͰදݱ͢Δ

    def sort[T](list: List[T])(implicit cmp: Comparator[T]): List[T] = { list match { case x :: xs => val (ys, zs) = xs.partition(a => cmp.compare(x, a) > 0) sort(ys) ++ List(x) ++ sort(zs) case Nil => Nil } }
  15. Πϯελϯεએݴͷଞͷํ๏ "OPUIFSXBZPGJOTUBODFEFDMBSBUJPO w “implicit def”XJUIOPQBSBNFUFSJTBMTPJOTUBODFEFDMBSBUJPO w 5IJTJTVTFEGPSEFDMBSJOHJOTUBODFXJUIHFOFSJDUZQF ܕҾ਺Λ࣋ͭܕͷΠϯελϯεએݴ͸JNQMJDJUEFGͰߦ͏ object Comparators

    { implicit def setSizeComparator[T]: Comparator[Set[T]] = {
 new Comparator[Set[T]] { def compare(a: Set[T], b: Set[T]): Int = a.size - b.size } } } Note: This comparator is not common for set.
  16. Πϯελϯεએݴͷଞͷํ๏ "OPUIFSXBZPGJOTUBODFEFDMBSBUJPO w *OTUBODFEFDMBSBUJPODBOIBWFUZQFDMBTTDPOTUSBJOU JNQMJDJUEFG΋ܕΫϥε੍໿Λ࣋ͭ͜ͱ͕Ͱ͖ɺ
 ͜ΕʹΑΓෳࡶͳܕͷΠϯελϯεએݴ͕Ͱ͖Δ object Comparators { implicit

    def tupleComparator[T1, T2] (implicit cmp1: Comparator[T1], cmp2: Comparator[T2]): Comparator[(T1, T2)] = {
 new Comparator[(T1, T2)] { def compare(a: (T1, T2), b: (T1, T2)): Int = { val res1 = cmp1.compare(a._1, b._1) if (res1 == 0) cmp2.compare(a._2, b._2) else res1 } } } }
  17. JNQMJDJUMZ<ʜ>DPNQBSF B C JTOPUJOUVJUJWF w 8FXBOUUPXSJUF“a > b”SBUIFSUIBO“….compare(a, b) >

    0” w 8FEPOPUXBOUUPFYQMJDJUMZXSJUFUZQFDMBTTJOTUBODF ܕΫϥεΠϯελϯεΛ໌ࣔతʹॻ͖ͨ͘ͳ͍ʂ import Comparators._ if (implicitly[Comparator[(Int, Int)]].compare((1, 2),(3, 4)) > 0) { … } if ((1, 2) > (3, 4)) { … } ௚ײతʹ෼͔ΓͮΒ͍
  18. ܕΫϥεΠϯελϯεͷͨΊͷ֦ுϝιου &YUFOTJPONFUIPETGPSUZQFDMBTTJOTUBODFT w 8FDBOEFDMBSFFYUFOTJPONFUIPECZ“implicit class” w “implicit class”DBOBMTPUBLFTUZQFDMBTTDPOTUSBJOU JNQMJDJUDMBTTͰطଘΫϥεʹϝιουΛੜ΍ͤΔ ܕ੍໿Λ͚ͭΕ͹ܕΫϥεΠϯελϯεͰͷΈ࢖͑ΔΑ͏ʹ

    object ComparatorSyntax { implicit class ComparatorOps[T](a: T) (implicit cmp: Comparator[T]) {
 def > (b: T): Boolean = cmp.compare(a, b) > 0 } } import Comparators._ import ComparatorSyntax._ (1, 2) > (2, 4) // return false
  19. 4DBMBʹ͓͚ΔJNQMJDJUͷҙຯ *NQMJDJUTJO4DBMB 4DBMBͰ͸༷ʑͳҙຯͰJNQMJDJU͕࢖ΘΕ͍ͯΔ no parameters one parameter implicit parameters implicit

    parameter typeclass constraint - - implicit val implicit object instance declaration - - implicit class Error! extension methods ◦ implicit def instance declaration implicit conversion ◦
  20. 4DBMBͷܕΫϥεϥΠϒϥϦ 5ZQFDMBTTMJCSBSJFTJO4DBMB w 5IFSFBSFUXPNBKPSMJCSBSJFT w 4DBMB[ w $BUT w 5IJTTMJEFCSJFGMZEFTDSJCFTQBDLBHFTUSVDUVSFPGUIFN

    w 6TFSTOFFEUPJNQPSUUZQFDMBTTFT JOTUBODFEFDMBSBUJPOT  BOEFYUFOTJPONFUIPETGPSVTJOHUIFTFMJCTXFMM ೋେܕΫϥεϥΠϒϥϦ4DBMB[ $BUT ͜ΕΒΛ্ख͘࢖͏ʹ͸ύοέʔδߏ଄Λ஌͓ͬͯ͘ඞཁ
  21. 4DBMB[ͷύοέʔδߏ੒ 1BDLBHFTUSVDUVSFPG4DBMB[ w TDBMB[  w UZQFDMBTTEFDMBSBUJPOT w TDBMB[TUE 

    w JOTUBODFEFDMBSBUJPOTPGDPNNPOUZQFT w TDBMB[TZOUBY  w FYUFOTJPONFUIPET TDBMB[TUEҎԼʹΠϯελϯεએݴ TDBMB[TZOUBYҎԼʹ֦ுϝιου͕ఆٛ͞Ε͍ͯΔ
  22. $BUTͷύοέʔδߏ੒ 1BDLBHFTUSVDUVSFPG$BUT w DBUT  w UZQFDMBTTEFDMBSBUJPOT w DBUTJOTUBODFT 

    w JOTUBODFEFDMBSBUJPOTPGDPNNPOUZQFT w DBUTTZOUBY  w FYUFOTJPONFUIPET $BUT΋ࣅͨΑ͏ͳύοέʔδͷߏ଄Λ͍ͯ͠Δ
  23. 4DBMBʹ͓͚ΔܕΫϥεΠϯελϯεએݴ 5ZQFDMBTTJOTUBODFEFDMBSBUJPOJO4DBMB • “delegate for”JTJOTUBODFEFDMBSBUJPO • 5IFOBNFPGEFMFHBUFJOTUBODFJTPQUJPOBM Πϯελϯεએݴ͸৽ͨʹEFMFHBUFGPSߏจ͕ಋೖ object Comparators

    { delegate IntComparator for Comparator[Int] { def compare(a: Int, b: Int): Int = a - b } delegate [T] for Comparator[Set[T]] { def compare(a: Set[T], b: Set[T]): Int = a.size - b.size } }
  24. 4DBMBʹ͓͚ΔܕΫϥε੍໿ͷॻ͖ํ 5ZQFDMBTTDPOTUSBJOUJO4DBMB w *O4DBMB QBSBNFUFSMJTUGPMMPXJOH“given”LFZXPSEFYQSFTTFT UZQFDMBTTDPOTUSBJOU ܕΫϥε੍໿͸HJWFOΩʔϫʔυͰએݴ͢Δ def sort[T](list: List[T])

    given (cmp: Comparator[T]): List[T] = { list match { case x :: xs => val (ys, zs) = xs.partition(a => cmp.compare(x, a) > 0) sort(ys) ++ List(x) ++ sort(zs) case Nil => Nil } }
  25. ܕΫϥεΠϯελϯεͷͨΊͷ֦ுϝιου &YUFOTJPONFUIPETGPSUZQFDMBTTJOTUBODFT w compareDBOBMTPCFFYUFOTJPONFUIPE w *OUIJTDBTF compareTIPVMECFJNQMFNFOUFEJOJOTUBODF EFDMBSBUJPO ܕΫϥε͕ཁٻ͢Δϝιου͕֦ுϝιουͰ΋ྑ͍ trait

    Comparator[T] { def (a: T) compare (b: T): Int def (a: T) > (b: T): Boolean = a.compare(b) > 0 } object Comparators { delegate for Comparator[Int] { def (a: Int) compare (b: Int): Int = a - b } }
  26. ܕΫϥε੍໿Λ࣋ͭΠϯελϯεએݴ *OTUBODFEFDMBSBUJPOXJUIUZQFDMBTTDPOTUSBJOU w “delegate for”EFDMBSBUJPODBOUBLF“given”DMBVTF w QBSBNFUFSOBNFJO“given”DMBVTFJTPQUJPOBM 4DBMBͱҟͳΓɺΠϯελϯεએݴ͸ৗʹEFMFHBUFGPS object Comparators

    { delegate TupleComparator [T1, T2] for Comparator[(T1, T2)] given Comparator[T1], Comparator[T2] { def (a: (T1, T2)) compare (b: (T1, T2)): Int = { val res1 = a._1.compare(b._1) if (res1 == 0) a._2.compare(b._2) else res1 } } }
  27. ·ͱΊ $PODMVTJPO 4DBMBͱ4DBMB͸ܕΫϥεͷॻ͖ํ͕େ͖͘ҧ͏ 4DBMBͷํ͕Θ͔Γ΍͍͢ typeclass declaration instance declaration typeclass constraint

    extension methods import instance declaration Scala2 trait implicit object/val/def implicit parameter implicit 
 class/def import Scala3 trait delegate for given extension methods import delegate