Generics
def zweimal[A](x: A): List[A] = List(x, x)
class Kiste[A](val inhalt: A):
def map[B](f: A => B): Kiste[B] = Kiste(f(inhalt))
override def toString = s"Kiste($inhalt)"
def groesster[A](l: List[A])(using ord: Ordering[A]): A = l.reduce((a, b) => if ord.gt(a, b) then a else b)
@main def main(): Unit =
println(zweimal("hi"))
println(Kiste(21).map(_ * 2))
println(groesster(List(3, 8, 5)))
println(groesster(List("b", "z", "a")))List(hi, hi) Kiste(42) 8 z
Funktionen höherer Ordnung und Currying
def addiere(a: Int)(b: Int): Int = a + b
val plus5 = addiere(5)
val verkette = (f: Int => Int, g: Int => Int) => f.andThen(g)
@main def main(): Unit =
println(plus5(10))
println(addiere(1)(2))
val f = verkette(_ + 1, _ * 10)
println(f(4))
val teilweise: Int => Int = math.max(3, _)
println(List(1, 5, 2).map(teilweise))
val zaehler = { var n = 0; () => { n += 1; n } }
println((zaehler(), zaehler(), zaehler()))15 3 50 List(3, 5, 3) (1,2,3)
Given und Using (Typklassen)
Typklassen erlauben neues Verhalten für bestehende Typen:
trait Beschreibbar[A]:
def beschreibe(a: A): String
given Beschreibbar[Int] with
def beschreibe(a: Int) = s"Zahl $a"
given Beschreibbar[String] with
def beschreibe(a: String) = s"Text '$a'"
given [A](using b: Beschreibbar[A]): Beschreibbar[List[A]] with
def beschreibe(l: List[A]) = l.map(b.beschreibe).mkString("[", ", ", "]")
def zeige[A](a: A)(using b: Beschreibbar[A]): String = b.beschreibe(a)
@main def main(): Unit =
println(zeige(5))
println(zeige("hi"))
println(zeige(List(1, 2)))Zahl 5 Text 'hi' [Zahl 1, Zahl 2]
Extension Methods
extension (s: String)
def istPalindrom: Boolean = s == s.reverse
def wiederhole(n: Int): String = s * n
extension [A](l: List[A])
def zweites: Option[A] = l.lift(1)
@main def main(): Unit =
println("anna".istPalindrom)
println("ab".wiederhole(3))
println(List(1, 2, 3).zweites)
println(List(1).zweites)true ababab Some(2) None
Opaque Types und Union Types
object Typen:
opaque type Meter = Double
object Meter:
def apply(d: Double): Meter = d
extension (m: Meter)
def wert: Double = m
def +(o: Meter): Meter = m + o
def zeige(x: Int | String): String = x match
case i: Int => s"Int $i"
case s: String => s"String $s"
@main def main(): Unit =
import Typen.*
println((Meter(1.5) + Meter(2)).wert)
println(zeige(3))
println(zeige("a"))3.5 Int 3 String a
Merke
- Generics
[A], Kontextparameter mitusingund Instanzen mitgiven - Typklassen = Trait +
given-Instanzen extensionfügt Methoden zu bestehenden Typen hinzuopaque typeund Union Types (A | B) sind neu in Scala 3
Aufgabe
Schreibe eine Typklasse Ordnung[A] mit Instanzen für Int und String.