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

Intro to typeclass in Scala

Intro to typeclass in Scala

Avatar for Kazuhiro Ichikawa

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