Schwarze MagieScalas Typsystem ausgenutzt
Lars Hupel
Schwarze MagieScalas Typsytem ausgenutztHerbstcampus 2011 – S32
Lars [email protected]
8. September 2011
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Über den Autor
I Informatik-Student, TU MünchenI Java-Programmierer seit 5 JahrenI Scala-Programmierer seit 2 JahrenI Interesse an formalen Methoden, Typsystemen, ...
Lars Hupel Schwarze Magie 8. September 2011 2 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Werbung
Scala EnthusiastenMetropolregion Nürnberg
Lars Hupel Schwarze Magie 8. September 2011 3 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Scalas Typsystem
I Grundlage bleibt objektorientiertI erweiterte TypinferenzI SingletonsI Existential typesI Definition-site varianceI Implizite Konversionen und ParameterI ...
Lars Hupel Schwarze Magie 8. September 2011 4 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Innere KlassenJava vs. Scala
Javaclass Outer {
class Inner {}
}
Outer o = new Outer();Outer.Inner i = o.new Inner();
Lars Hupel Schwarze Magie 8. September 2011 5 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Innere KlassenJava vs. Scala
JavaI nicht-statische innere Klassen haben Referenz auf äußere
KlasseI Instanziierung benötigt äußeres ObjektI aber: alle inneren Objekte haben selben Typ
Lars Hupel Schwarze Magie 8. September 2011 6 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Innere KlassenJava vs. Scala
JavaI nicht-statische innere Klassen haben Referenz auf äußere
KlasseI Instanziierung benötigt äußeres ObjektI aber: alle inneren Objekte haben selben Typ
Lars Hupel Schwarze Magie 8. September 2011 6 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Innere KlassenJava vs. Scala
Scalaclass Outer {
class Inner}
val outer = new Outer()val i1: outer.Inner = new outer.Inner()val i2: Outer#Inner = i1
Lars Hupel Schwarze Magie 8. September 2011 7 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Innere KlassenJava vs. Scala
ScalaI Referenz auf äußeres Objekt wird Teil des TypsI innere Objekte zweier verschiedener äußerer Objekte nicht
miteinander kompatibelI Probleme bei Java-InteroperabilitätI Lösung: Projektion Outer#Inner
Lars Hupel Schwarze Magie 8. September 2011 8 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Bereichsdatentyp
I eine Objekt ist mit einem Zahlenbereich assoziiertI Methoden dieses Objekts sollen nun nur auf Zahlen aus
diesem Bereich operierenI Zahlen außerhalb des Bereichs sollen zu Compiler-Fehler
führen
Lars Hupel Schwarze Magie 8. September 2011 9 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Bereichsdatentyp
I eine Objekt ist mit einem Zahlenbereich assoziiertI Methoden dieses Objekts sollen nun nur auf Zahlen aus
diesem Bereich operierenI Zahlen außerhalb des Bereichs sollen zu Compiler-Fehler
führen
Lars Hupel Schwarze Magie 8. September 2011 9 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
BereichsdatentypImplementation
class Range(begin: Int, end: Int) {class RangeInt private[Range](val n: Int) {
def next: Option[Range.this.RangeInt] =if (n < end) Some(new RangeInt(n+1))else None
}
def first = new RangeInt(begin)def last = new RangeInt(end)
}
class HasRange {val myRange: Range = new Range(1, 10)def func(i: myRange.RangeInt) = println(i.n)
}Lars Hupel Schwarze Magie 8. September 2011 10 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
BereichsdatentypVerwendung
> new HasRange()res0: HasRange = HasRange@5b927504> res0.func(res0.myRange.first)1
> new Range(11, 20)res1: Range = Range@790f2f3c> res0.func(res1.first)error: type mismatch;found : res1.RangeIntrequired: res0.myRange.RangeInt
Lars Hupel Schwarze Magie 8. September 2011 11 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Singletons
Scala ordnet einigen Werten einen eindeutigen Typen zu, der abernicht immer inferiert wird
> class Foo> val foo = new Foo {}foo: Foo = Foo@608a6351
> checkType(foo)Foo
> checkType[foo.type](foo)[email protected]
Lars Hupel Schwarze Magie 8. September 2011 12 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Singletons und Implicitsapply/update
class Sugar {def apply(i: Int) = idef update(i: Int, value: Int) = ()
}
val sugar = new Sugar()
sugar(3) sugar.apply(3)sugar(3) = 5 sugar.update(3, 5)
Lars Hupel Schwarze Magie 8. September 2011 13 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Singletons und ImplicitsSymbol
’a Symbol.apply("a")’a = 0 Symbol.update("a", 0)
aber: Symbol hat keine update-Methode
Lars Hupel Schwarze Magie 8. September 2011 14 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Singletons und ImplicitsSymbol
’a Symbol.apply("a")’a = 0 Symbol.update("a", 0)
aber: Symbol hat keine update-Methode
Lars Hupel Schwarze Magie 8. September 2011 14 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Singletons und ImplicitsSymbol
implicit def pimpSymbol(s: Symbol.type) = new {def update(str: String, newVal: Any) =
println(str + " := " + newVal)}
> ’a = "foo"a := foo
Lars Hupel Schwarze Magie 8. September 2011 15 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Collections in 2.8
Scalas Collections wurden mit 2.8 komplett überarbeitet:Transformationen liefern immer den bestmöglichen Typ
möglich durch CanBuildFrom
Lars Hupel Schwarze Magie 8. September 2011 16 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Collections in 2.8
Scalas Collections wurden mit 2.8 komplett überarbeitet:Transformationen liefern immer den bestmöglichen Typ
möglich durch CanBuildFrom
Lars Hupel Schwarze Magie 8. September 2011 16 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
CanBuildFrom
trait CanBuildFrom[-From, -Elem, +To] {
def apply(from: From): Builder[Elem, To]
def apply(): Builder[Elem, To]
}
Lars Hupel Schwarze Magie 8. September 2011 17 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
CanBuildFrom
CanBuildFrom ermöglicht es, über Collections zu abstrahieren
CanBuildFrom[From, Elem, To] bedeutet: es ist möglich...I auf Grundlage einer Collection des Typs FromI mit Elementen des Zieltyps ElemI eine Collection des Typs To
... zu erstellen
Lars Hupel Schwarze Magie 8. September 2011 18 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
CanBuildFrom
CanBuildFrom ermöglicht es, über Collections zu abstrahieren
CanBuildFrom[From, Elem, To] bedeutet: es ist möglich...I auf Grundlage einer Collection des Typs FromI mit Elementen des Zieltyps ElemI eine Collection des Typs To
... zu erstellen
Lars Hupel Schwarze Magie 8. September 2011 18 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
CanBuildFrom
CanBuildFrom ermöglicht es, über Collections zu abstrahieren
CanBuildFrom[From, Elem, To] bedeutet: es ist möglich...I auf Grundlage einer Collection des Typs FromI mit Elementen des Zieltyps ElemI eine Collection des Typs To
... zu erstellen
Lars Hupel Schwarze Magie 8. September 2011 18 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
CanBuildFrom
CanBuildFrom ermöglicht es, über Collections zu abstrahieren
CanBuildFrom[From, Elem, To] bedeutet: es ist möglich...I auf Grundlage einer Collection des Typs FromI mit Elementen des Zieltyps ElemI eine Collection des Typs To
... zu erstellen
Lars Hupel Schwarze Magie 8. September 2011 18 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
QuicksortSchritt 1: Signatur definieren
Traversable
Iterable
Seq Set Map
IndexedSeq LinearSeq SortedSet BitSet SortedMap
http://www.decodified.com/scala/collections-api.xml, Mathias, CC-by 3.0
Lars Hupel Schwarze Magie 8. September 2011 19 / 61
http://www.decodified.com/scala/collections-api.xml
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
QuicksortSchritt 1: Signatur definieren
def sort[T, Coll](a: Coll)(implicit ev: Coll
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
QuicksortSchritt 1: Signatur definieren
def sort[T, Coll](a: Coll)(implicit ev: Coll
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
QuicksortSchritt 1: Signatur definieren
def sort[T, Coll](a: Coll)(implicit ev: Coll
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
QuicksortSchritt 1: Signatur definieren
def sort[T, Coll](a: Coll)(implicit ev: Coll
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
QuicksortSchritt 1: Signatur definieren
def sort[T, Coll](a: Coll)(implicit ev: Coll
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
QuicksortSchritt 2: Implementation
Demo
Lars Hupel Schwarze Magie 8. September 2011 23 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Werte und TypenTerminologie
I Datenkonstruktoren erzeugen DatenI in Java: „Konstruktoren“I Typkonstruktoren erzeugen TypenI in Java: „generische Klasse“I auch bekannt als „parametrische Polymorphie“
Lars Hupel Schwarze Magie 8. September 2011 24 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Werte und TypenTerminologie
I Datenkonstruktoren erzeugen DatenI in Java: „Konstruktoren“I Typkonstruktoren erzeugen TypenI in Java: „generische Klasse“I auch bekannt als „parametrische Polymorphie“
Lars Hupel Schwarze Magie 8. September 2011 24 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Werte und TypenTerminologie
I Datenkonstruktoren erzeugen DatenI in Java: „Konstruktoren“I Typkonstruktoren erzeugen TypenI in Java: „generische Klasse“I auch bekannt als „parametrische Polymorphie“
Lars Hupel Schwarze Magie 8. September 2011 24 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Werte und TypenTerminologie
I Datenkonstruktoren erzeugen DatenI in Java: „Konstruktoren“I Typkonstruktoren erzeugen TypenI in Java: „generische Klasse“I auch bekannt als „parametrische Polymorphie“
Lars Hupel Schwarze Magie 8. September 2011 24 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Werte und TypenKinds
„Kind“ bezeichnet die Struktur eines Typkonstruktors
NotationI * steht für beliebigen TypI -> steht für Abbildung
Lars Hupel Schwarze Magie 8. September 2011 25 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Werte und TypenKinds
„Kind“ bezeichnet die Struktur eines Typkonstruktors
NotationI * steht für beliebigen TypI -> steht für Abbildung
Lars Hupel Schwarze Magie 8. September 2011 25 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Werte und TypenKinds
„Kind“ bezeichnet die Struktur eines Typkonstruktors
NotationI * steht für beliebigen TypI -> steht für Abbildung
Lars Hupel Schwarze Magie 8. September 2011 25 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Typen und KindsBeispiele
Typ Deklaration KindListe class List[A] * -> *Paar class Tuple2[A, B] (* x *) -> *Applikation type Ap[T[_], S] = T[S] ((* -> *) x *) -> *
Lars Hupel Schwarze Magie 8. September 2011 26 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Methoden und Funktionen
I Methoden sind keine first class citizenI Funktionen sind „gewöhnliche“ Objekte mit apply-MethodeI Methode −→ Funktion per f _
aber: Was ist mit generischen Methoden?
Lars Hupel Schwarze Magie 8. September 2011 27 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Methoden und Funktionen
I Methoden sind keine first class citizenI Funktionen sind „gewöhnliche“ Objekte mit apply-MethodeI Methode −→ Funktion per f _
aber: Was ist mit generischen Methoden?
Lars Hupel Schwarze Magie 8. September 2011 27 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Methoden und FunktionenNotwendigkeit von Kinds
def transform[A](opt: Option[A]): List[A] =opt.toList
> transform _res0: Option[Nothing] => List[Nothing] =
Lars Hupel Schwarze Magie 8. September 2011 28 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Methoden und FunktionenNotwendigkeit von Kinds
trait ~>[-A[_], +B[_]] {def apply[T](a: A[T]): B[T]
}
new (Option ~> List) {def apply[T](opt: Option[T]): List[T] =
opt.toList}
Erkenntnis: Kinds erhöhen die Ähnlichkeit von Methoden undFunktionen
Lars Hupel Schwarze Magie 8. September 2011 29 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Methoden und FunktionenNotwendigkeit von Kinds
trait ~>[-A[_], +B[_]] {def apply[T](a: A[T]): B[T]
}
new (Option ~> List) {def apply[T](opt: Option[T]): List[T] =
opt.toList}
Erkenntnis: Kinds erhöhen die Ähnlichkeit von Methoden undFunktionen
Lars Hupel Schwarze Magie 8. September 2011 29 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Kindinferenz
I ... ist so gut wie nicht vorhandenI explizite Deklaration erforderlichI Inferenz der Parameter beim Aufruf einer solchen Methode
schlägt oft fehl
Lars Hupel Schwarze Magie 8. September 2011 30 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Typäquivalenz
Problemgenerische Klasse, bei der einige Methoden nur bei speziellenTypparametern angeboten werden
Lösung: impliziter „Beweis“
Lars Hupel Schwarze Magie 8. September 2011 31 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Typäquivalenz
Problemgenerische Klasse, bei der einige Methoden nur bei speziellenTypparametern angeboten werden
Lösung: impliziter „Beweis“
Lars Hupel Schwarze Magie 8. September 2011 31 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Naive Implementation
class =:=[From, To] extends (From => To)
implicit def tpEquals[A] = new =:=[A, A]
DisclaimerI Zugriffsschutz fehltI Casten kann nicht verhindert werden
Lars Hupel Schwarze Magie 8. September 2011 32 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Naive ImplementationVerwendung
trait Generic[A] {
val a: A
def onlyForString(implicit ev: A =:= String) =a.charAt(0)
}
Lars Hupel Schwarze Magie 8. September 2011 33 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Naive Implementation
NachteileI aus A =:= B kann nicht B =:= A konstruiert werdenI aus A =:= B und B =:= C kann nicht A =:= C konstruiert
werdenI aus A =:= B kann nicht F[A] =:= F[B] konstruiert werdenI keine vollständige Äquivalenz auf Typebene
Lars Hupel Schwarze Magie 8. September 2011 34 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Naive Implementation
NachteileI aus A =:= B kann nicht B =:= A konstruiert werdenI aus A =:= B und B =:= C kann nicht A =:= C konstruiert
werdenI aus A =:= B kann nicht F[A] =:= F[B] konstruiert werdenI keine vollständige Äquivalenz auf Typebene
Lars Hupel Schwarze Magie 8. September 2011 34 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Naive Implementation
NachteileI aus A =:= B kann nicht B =:= A konstruiert werdenI aus A =:= B und B =:= C kann nicht A =:= C konstruiert
werdenI aus A =:= B kann nicht F[A] =:= F[B] konstruiert werdenI keine vollständige Äquivalenz auf Typebene
Lars Hupel Schwarze Magie 8. September 2011 34 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Naive Implementation
NachteileI aus A =:= B kann nicht B =:= A konstruiert werdenI aus A =:= B und B =:= C kann nicht A =:= C konstruiert
werdenI aus A =:= B kann nicht F[A] =:= F[B] konstruiert werdenI keine vollständige Äquivalenz auf Typebene
Lars Hupel Schwarze Magie 8. September 2011 34 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Naive Implementation
NachteileI aus A =:= B kann nicht B =:= A konstruiert werdenI aus A =:= B und B =:= C kann nicht A =:= C konstruiert
werdenI aus A =:= B kann nicht F[A] =:= F[B] konstruiert werdenI keine vollständige Äquivalenz auf Typebene
Lars Hupel Schwarze Magie 8. September 2011 34 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Implementation mit Kinds
trait Leibniz[A,B] {def subst[F[_]](p: F[A]) : F[B]
}
abgekürzt als A ~ B
Lars Hupel Schwarze Magie 8. September 2011 35 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Implementation mit Kinds
F[A] A~B F[B]
Lars Hupel Schwarze Magie 8. September 2011 36 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Implementation mit KindsKonvertierungsfunktion
Wie bekommt man aus A ~ B ein A => B?
F[A]A=>A B=>A
A~B F[B]
Lars Hupel Schwarze Magie 8. September 2011 37 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Implementation mit KindsKonvertierungsfunktion
Wie bekommt man aus A ~ B ein A => B?
F[A]A=>A B=>A
A~B F[B]
Lars Hupel Schwarze Magie 8. September 2011 37 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Implementation mit KindsKonvertierungsfunktion
def witness[A,B](f: A ~ B): A => B =f.subst(identity[A] _)
argument expression’s type is not compatiblewith formal parameter type;found : A => Arequired: ?F[A]
Lars Hupel Schwarze Magie 8. September 2011 38 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Implementation mit KindsKonvertierungsfunktion
def witness[A,B](f: A ~ B): A => B =f.subst(identity[A] _)
argument expression’s type is not compatiblewith formal parameter type;found : A => Arequired: ?F[A]
Lars Hupel Schwarze Magie 8. September 2011 38 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Implementation mit KindsKonvertierungsfunktion
def witness[A,B](f: A ~ B): A => B =f.subst[({type L[X]=A => X})#L](identity)
Lars Hupel Schwarze Magie 8. September 2011 39 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Implementation mit KindsInversion
F[A]A~A B~A
A~B F[B]
def symm[A,B](f: A ~ B) : B ~ A =f.subst[({type L[X]=X ~ A})#L](refl)
Lars Hupel Schwarze Magie 8. September 2011 40 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Implementation mit KindsLifting
F[A]T[A]~T[A]
A~B F[B]T[A]~T[B]
def lift[T[_], A, B](a: A ~ B): (T[A] ~ T[B]) = {type L[X] = T[A] ~ T[X]a.subst[L](refl)
}
Lars Hupel Schwarze Magie 8. September 2011 41 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Heterogeneous Lists
ProblemFunktionen mit mehreren Rückgabewerten
Standardlösung: Verwendung von Tupeln
Lars Hupel Schwarze Magie 8. September 2011 42 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Heterogeneous Lists
Nachteile von TupelnI in Scala: jede Stelligkeit eigene KlasseI begrenzte Stelligkeit
Lösung: Heterogeneous Lists(statisch typisierte) Listen mit uneinheitlichen Elementtypen
Lars Hupel Schwarze Magie 8. September 2011 43 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Heterogeneous Lists
Nachteile von TupelnI in Scala: jede Stelligkeit eigene KlasseI begrenzte Stelligkeit
Lösung: Heterogeneous Lists(statisch typisierte) Listen mit uneinheitlichen Elementtypen
Lars Hupel Schwarze Magie 8. September 2011 43 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Heterogeneous Lists
Nachteile von TupelnI in Scala: jede Stelligkeit eigene KlasseI begrenzte Stelligkeit
Lösung: Heterogeneous Lists(statisch typisierte) Listen mit uneinheitlichen Elementtypen
Lars Hupel Schwarze Magie 8. September 2011 43 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Implementation
sealed trait HList
final case class HCons[H, T
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Verwendung
Erzeugung
> def getValues = 3 :: "foo" :: HNilgetValues: HCons[Int,HCons[String,HNil.type]]
> getValuesres0: HCons[...] = HCons(3,HCons(foo,HNil))
Lars Hupel Schwarze Magie 8. September 2011 45 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Verwendung
Pattern Matching
> getValues match { case HCons(x, _) => x }res0: Int = 3
> getValues match {case HCons(_, HCons(y, _)) => y
}res1: String = foo
Lars Hupel Schwarze Magie 8. September 2011 46 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
VerwendungIndexbasierter Zugriff
I eine Funktion HList[H, T] => Int => Any möglich, abernicht hilfreich
I Idee: index-Funktion muss einen Typparameter haben, derdie Position in der Liste repräsentiert
Lösung: Peano-Numerale
Lars Hupel Schwarze Magie 8. September 2011 47 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
VerwendungIndexbasierter Zugriff
I eine Funktion HList[H, T] => Int => Any möglich, abernicht hilfreich
I Idee: index-Funktion muss einen Typparameter haben, derdie Position in der Liste repräsentiert
Lösung: Peano-Numerale
Lars Hupel Schwarze Magie 8. September 2011 47 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Peano-Numerale
Wertbasierttrait Natcase object Zerocase class Succ(n: Nat)
val two = Succ(Succ(Zero))
Lars Hupel Schwarze Magie 8. September 2011 48 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Peano-Numerale
Typbasiert
trait Nattrait Zero extends Nattrait Succ[N
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Peano-Numerale und HListsZugriffstrait
trait AccessN[L
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Peano-Numerale und HListsHCons revisited
case class HCons[H, T
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Peano-Numerale und HListsImplementation
implicit def accessZero[H, T
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Peano-Numerale und HLists
3 foo 5.3 Nil
Zero
HCons[String, HCons[Double,HNil.type]HCons[Int,
Succ[ ]
]]
Lars Hupel Schwarze Magie 8. September 2011 53 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Peano-Numerale und HListsVerwendung
val _0 = new Zero {}val _1 = new Succ[Zero] {}val _2 = ...
Lars Hupel Schwarze Magie 8. September 2011 54 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Peano-Numerale und HListsVerwendung
> val list = 3 :: "foo" :: 5.3 :: HNil
> list(_0)res0: Int = 3
> list(_1)res1: String = foo
> list(_3)error: could not find implicit value for parameter ...
Lars Hupel Schwarze Magie 8. September 2011 55 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Heterogeneous Lists
VorteileI Verwalten von verschiedenen Typen, ohne eine Klasse anlegen
zu müssenI Tupel beliebiger StelligkeitI kein Verlust von Typinformationen verglichen mit List[Any]I Compiler kann falsche Verwendung erkennenI dank Scalas Syntaxzucker „fühlen“ sich HLists wie normale
Listen anI sind auch in Java möglich, aber viel Overhead nötig
Lars Hupel Schwarze Magie 8. September 2011 56 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Anwendung
Problem: Signatur von String.format stellt nicht sicher, dass dieArgumente zum Formatstring passen Compiler kann Fehler nicht aufspüren
Idee: Funktion konstruieren, die eine HList von den Argumentennimmt und diese formatiert
Lars Hupel Schwarze Magie 8. September 2011 57 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Anwendung
Problem: Signatur von String.format stellt nicht sicher, dass dieArgumente zum Formatstring passen Compiler kann Fehler nicht aufspüren
Idee: Funktion konstruieren, die eine HList von den Argumentennimmt und diese formatiert
Lars Hupel Schwarze Magie 8. September 2011 57 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Typsicheres printfImplementation
Demo
Lars Hupel Schwarze Magie 8. September 2011 58 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Typsicheres printf
VorteileI Compiler kann Formatierung prüfenI weniger ExceptionsI selbst definierte Operatoren erhöhen (richtig eingesetzt) die
Lesbarkeit
Lars Hupel Schwarze Magie 8. September 2011 59 / 61
Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists
Typsicheres printf
NachteileI gezeigte Lösung vereinfacht, benötigt noch Tricks zum LaufenI Fehlermeldungen können sehr unübersichtlich werdenI „Denken in Typen“ erfordert in der Regel einige Eingewöhnung
Lars Hupel Schwarze Magie 8. September 2011 60 / 61
Fragen?
http://www.lars-hupel.dehttp://gplus.to/larsrh
http://www.lars-hupel.dehttp://gplus.to/larsrh