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

Opaque Types in Scala 3

Opaque Types in Scala 3

Ein kurzer Überblick über Opaque Types und Unterschiede zu Refined Types.

Jens Grassel

May 12, 2022
Tweet

More Decks by Jens Grassel

Other Decks in Programming

Transcript

  1. Also laut Doku... “Opaque types o er a sound abstraction

    over implementation details, without imposing performance overhead.” • Das klingt gut, aber Was heißt das? • Im Grunde: wie Type-Aliase, nur besser • statt: type Email = String • nehmen wir: opaque type Email = String
  2. Unterschiede zu einfachen Type-Aliasen Type-Aliases geben nicht mehr Sicherheit: type

    Email = String def test(e: Email): String = ??? val str: String = "Just a string" test(str) // Wird compilieren... Opaque Types dagegen schon: opaque type Email = String def test(e: Email): String = ??? val str: String = "Just a string" test(str) // -> Type Mismatch Error!
  3. Boilerplate... Boilerplate im Companion-Object: opaque type Email object Email {

    def apply(s: String): Email = s def from(s: String): Option[Email] = ??? } Erweiterung via Extension Methods: extension (e: Email) { def domain: DomainName = ??? }
  4. Wie sicher ist das? val e = Email(null) // WIRD

    COMPILIEREN! val d = e.domain // -> AUTSCH! val e = Email.from(null) // besser (-> None) Achtung! Das bedeutet, daß es keine(!) ¨ Uberpr¨ ufung der Typerzeugung zur Compilierzeit gibt wie bei Refined Types!
  5. Warum dann? • erspart uns Wrapper-Klassen • Typensicherheit abseits der

    Initialisierung trotzdem zur Compilierzeit • erm¨ oglicht spezifische from oder validate Methoden analog zu Refined • Operationen auf diesen Typen (Eq, Semigroup, Monoid) k¨ onnen definiert werden • weitere Operationen einfach via Extension Methods • Es gibt noch kein Refined (zumindest nicht vollst¨ andig) f¨ ur Scala . :-(
  6. Vor- und Nachteile • keine ¨ Uberpr¨ ufung der Initialisierung

    zur Compilierzeit (das Killerfeature von Refined) • viel mehr Boilerplate • viel, viel mehr Boilerplate f¨ ur diverse Operationen, die mit Refined “frei Haus” kommen • Opaque Types sollten performanter sein, da Refined die Value Classes benutzt • keine “magische” Konvertierung mehr, die ggf. nur ¨ uber zus¨ atzliche Annotationen funktioniert
  7. Besonderheiten Achtung! Die Definition von Funktionen ist notwendig, die zum

    Ursprungstyp zur¨ uck f¨ uhren! extension (e: Email): def toString: String = e extension (p: PortNumber): def toInt: Int = p