
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 terbaruScala 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
.