Skala 3: menyingkirkan implisit. Kelas tipe







Artikel saya sebelumnya adalah tentang konversi implisit dan metode ekstensi. Pada artikel ini, kita akan membahas cara baru untuk mendeklarasikan kelas tipe di Scala 3.







Setelah mempelajari cara menambahkan metode eksternal ke kelas arbitrer, kami ingin melangkah lebih dalam lagi, yaitu mempelajari cara mengonversi kelas arbitrer menjadi antarmuka "eksternal", yaitu tanpa mewarisinya secara langsung. Tugas ini diselesaikan dengan kelas tipe.







Tapi pertama-tama, mari kita cari tahu apa itu kelas tipe. Seperti konsep itu sendiri, istilah " kelas tipe" berasal dari Haskell. Kata "kelas" yang digunakan di sini bukan dalam arti sempit yang diterima di OOP, tetapi dalam arti yang lebih luas - sebagai sebutan dari sekumpulan entitas yang memiliki kesamaan. (Saya mengerti bahwa kebanyakan orang yang akan membaca artikel ini memiliki latar belakang OOP, dan bagi mereka istilah "kelas tipe" terdengar seperti "minyak minyak", meskipun itu berarti "kategori minyak". Untuk menghindari kebingungan dengan kelas-OOP konvensional , alih-alih "type class", saya hanya akan menggunakan transliterasi "typeclass" - kira-kira transl.)







Sintaks contoh sudah terbaru Scala 3.0.0-M3



.

, , , . Scala 3:







// Adapted from this Dotty documentation:
// https://dotty.epfl.ch/docs/reference/contextual/type-classes.html

trait Semigroup[T]:
  extension (t: T)
    def combine(other: T): T
    def <+>(other: T): T = t.combine(other)

trait Monoid[T] extends Semigroup[T]:
  def unit: T
      
      





, <+>



. β€” , , 0 β€” . , Semigroup



Monoid



.







Semigroup



T



extension- combine



<+>



, combine



. unit



Monoid



, extension-. , unit



T



, , , T



, .







:







given StringMonoid: Monoid[String] with
  def unit: String = ""
  extension (s: String) def combine(other: String): String = s + other

given IntMonoid: Monoid[Int] with
  def unit: Int = 0
  extension (i: Int) def combine(other: Int): Int = i + other
      
      





. , given foo: Bar



β€” implicit-. Scala3 REPL, , : StringMonoid



IntMonoid



.







- :







"2" <+> ("3" <+> "4")             // "234"
("2" <+> "3") <+> "4"             // "234"
StringMonoid.unit <+> "2"         // "2"
"2" <+> StringMonoid.unit         // "2"

2 <+> (3 <+> 4)                   // 9
(2 <+> 3) <+> 4                   // 9
IntMonoid.unit <+> 2              // 2
2 <+> IntMonoid.unit              // 2
      
      





StringMonoid



IntMonoid



unit



. <+>



extension-, String



Int



. <+>



, .







: given Monoid[String] with ...



. unit



summon[Monoid[String]]



. summon



β€” implicitly



, implicit- . given_Monoid_String



, , .







, , - ( unit



). .







, . , , IntMonoid



Numeric[T]



:







given NumericMonoid[T](using num: Numeric[T]): Monoid[T] with
  def unit: T = num.zero
  extension (t: T) def combine(other: T): T = num.plus(t, other)

2.2 <+> (3.3 <+> 4.4)             // 9.9
(2.2 <+> 3.3) <+> 4.4             // 9.9

BigDecimal(3.14) <+> NumericMonoid.unit
NumericMonoid[BigDecimal].unit  <+> BigDecimal(3.14)
      
      





using



, Scala 2 implicit



. .







. NumericMonoid



β€” , Monoid[T]



β€” . T



, . NumericMonoid[BigDecimal]



, NumericMonoid



BigDecimal



. num



β€” NumericMonoid



, using



.







, unit



. -, <+>



. Scala obj1.method(obj2)



.







?



using



.








All Articles