Scala 3: deshacerse de los archivos implícitos. Clases de tipo







Mi artículo anterior trataba sobre conversiones implícitas y métodos de extensión. En este artículo, discutiremos la nueva forma de declarar clases de tipos en Scala 3.







Habiendo aprendido cómo agregar métodos externos a clases arbitrarias, queremos profundizar aún más, es decir, aprender a convertir clases arbitrarias en interfaces "externas", es decir, sin heredar directamente de ellas. Esta tarea se resuelve mediante clases de tipos.







Pero primero, averigüemos qué es una clase de tipos. Al igual que el concepto en sí, el término " clase de tipo" se originó en Haskell. La palabra "clase" se utiliza aquí no en el sentido estricto que se acepta en la programación orientada a objetos, sino en un sentido más amplio, como una designación de un conjunto de entidades que tienen algo en común. (Entiendo que la mayoría de las personas que leerán este artículo tienen antecedentes de OOP, y para ellos el término "tipo de clase" suena como "aceite de aceites", aunque significa "categoría de aceites". Para evitar confusiones con las clases de OOP convencionales , en lugar de "type class", solo usaré la transliteración "typeclass" - aprox. transl.)







La sintaxis de los ejemplos está actualizada 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