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

Schwarze Magie – Scalas Typsystem ausgenutzt

Lars Hupel
September 08, 2011

Schwarze Magie – Scalas Typsystem ausgenutzt

Lars Hupel

September 08, 2011
Tweet

More Decks by Lars Hupel

Other Decks in Programming

Transcript

  1. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Über den

    Autor Informatik-Student, TU München Java-Programmierer seit 5 Jahren Scala-Programmierer seit 2 Jahren Interesse an formalen Methoden, Typsystemen, ... Lars Hupel Schwarze Magie 8. September 2011 2 / 61
  2. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Werbung Scala

    Enthusiasten Metropolregion Nürnberg Lars Hupel Schwarze Magie 8. September 2011 3 / 61
  3. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Scalas Typsystem

    Grundlage bleibt objektorientiert erweiterte Typinferenz Singletons Existential types Definition-site variance Implizite Konversionen und Parameter ... Lars Hupel Schwarze Magie 8. September 2011 4 / 61
  4. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Innere Klassen

    Java vs. Scala Java class Outer { class Inner { } } Outer o = new Outer(); Outer.Inner i = o.new Inner(); Lars Hupel Schwarze Magie 8. September 2011 5 / 61
  5. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Innere Klassen

    Java vs. Scala Java nicht-statische innere Klassen haben Referenz auf äußere Klasse Instanziierung benötigt äußeres Objekt aber: alle inneren Objekte haben selben Typ Lars Hupel Schwarze Magie 8. September 2011 6 / 61
  6. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Innere Klassen

    Java vs. Scala Java nicht-statische innere Klassen haben Referenz auf äußere Klasse Instanziierung benötigt äußeres Objekt aber: alle inneren Objekte haben selben Typ Lars Hupel Schwarze Magie 8. September 2011 6 / 61
  7. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Innere Klassen

    Java vs. Scala Scala class 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
  8. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Innere Klassen

    Java vs. Scala Scala Referenz auf äußeres Objekt wird Teil des Typs innere Objekte zweier verschiedener äußerer Objekte nicht miteinander kompatibel Probleme bei Java-Interoperabilität Lösung: Projektion Outer#Inner Lars Hupel Schwarze Magie 8. September 2011 8 / 61
  9. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Bereichsdatentyp eine

    Objekt ist mit einem Zahlenbereich assoziiert Methoden dieses Objekts sollen nun nur auf Zahlen aus diesem Bereich operieren Zahlen außerhalb des Bereichs sollen zu Compiler-Fehler führen Lars Hupel Schwarze Magie 8. September 2011 9 / 61
  10. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Bereichsdatentyp eine

    Objekt ist mit einem Zahlenbereich assoziiert Methoden dieses Objekts sollen nun nur auf Zahlen aus diesem Bereich operieren Zahlen außerhalb des Bereichs sollen zu Compiler-Fehler führen Lars Hupel Schwarze Magie 8. September 2011 9 / 61
  11. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Bereichsdatentyp Implementation

    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
  12. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Bereichsdatentyp Verwendung

    > 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.RangeInt required: res0.myRange.RangeInt Lars Hupel Schwarze Magie 8. September 2011 11 / 61
  13. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Singletons Scala

    ordnet einigen Werten einen eindeutigen Typen zu, der aber nicht 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
  14. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Singletons und

    Implicits apply/update class Sugar { def apply(i: Int) = i def 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
  15. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Singletons und

    Implicits Symbol ’a Symbol.apply("a") ’a = 0 Symbol.update("a", 0) Lars Hupel Schwarze Magie 8. September 2011 14 / 61
  16. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Singletons und

    Implicits Symbol ’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
  17. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Singletons und

    Implicits Symbol 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
  18. Ü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
  19. Ü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
  20. Ü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
  21. Ü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... auf Grundlage einer Collection des Typs From mit Elementen des Zieltyps Elem eine Collection des Typs To ... zu erstellen Lars Hupel Schwarze Magie 8. September 2011 18 / 61
  22. Ü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... auf Grundlage einer Collection des Typs From mit Elementen des Zieltyps Elem eine Collection des Typs To ... zu erstellen Lars Hupel Schwarze Magie 8. September 2011 18 / 61
  23. Ü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... auf Grundlage einer Collection des Typs From mit Elementen des Zieltyps Elem eine Collection des Typs To ... zu erstellen Lars Hupel Schwarze Magie 8. September 2011 18 / 61
  24. Ü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... auf Grundlage einer Collection des Typs From mit Elementen des Zieltyps Elem eine Collection des Typs To ... zu erstellen Lars Hupel Schwarze Magie 8. September 2011 18 / 61
  25. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Quicksort Schritt

    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
  26. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Quicksort Schritt

    1: Signatur definieren def sort[T, Coll](a: Coll) (implicit ev: Coll <:< SeqLike[T, Coll], cbf: CanBuildFrom[Coll, T, Coll], n: Ordering[T]): Coll Lars Hupel Schwarze Magie 8. September 2011 20 / 61
  27. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Quicksort Schritt

    1: Signatur definieren def sort[T, Coll](a: Coll) (implicit ev: Coll <:< SeqLike[T, Coll], cbf: CanBuildFrom[Coll, T, Coll], n: Ordering[T]): Coll ev: Coll Subtyp von SeqLike[T, Coll]? SeqLike[T, Coll]: Transformationen auf Coll erhalten den Typ Coll, wenn ... ein entsprechendes CanBuildFrom vorhanden ist Lars Hupel Schwarze Magie 8. September 2011 22 / 61
  28. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Quicksort Schritt

    1: Signatur definieren def sort[T, Coll](a: Coll) (implicit ev: Coll <:< SeqLike[T, Coll], cbf: CanBuildFrom[Coll, T, Coll], n: Ordering[T]): Coll ev: Coll Subtyp von SeqLike[T, Coll]? SeqLike[T, Coll]: Transformationen auf Coll erhalten den Typ Coll, wenn ... ein entsprechendes CanBuildFrom vorhanden ist Lars Hupel Schwarze Magie 8. September 2011 22 / 61
  29. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Quicksort Schritt

    1: Signatur definieren def sort[T, Coll](a: Coll) (implicit ev: Coll <:< SeqLike[T, Coll], cbf: CanBuildFrom[Coll, T, Coll], n: Ordering[T]): Coll ev: Coll Subtyp von SeqLike[T, Coll]? SeqLike[T, Coll]: Transformationen auf Coll erhalten den Typ Coll, wenn ... ein entsprechendes CanBuildFrom vorhanden ist Lars Hupel Schwarze Magie 8. September 2011 22 / 61
  30. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Quicksort Schritt

    1: Signatur definieren def sort[T, Coll](a: Coll) (implicit ev: Coll <:< SeqLike[T, Coll], cbf: CanBuildFrom[Coll, T, Coll], n: Ordering[T]): Coll ev: Coll Subtyp von SeqLike[T, Coll]? SeqLike[T, Coll]: Transformationen auf Coll erhalten den Typ Coll, wenn ... ein entsprechendes CanBuildFrom vorhanden ist Lars Hupel Schwarze Magie 8. September 2011 22 / 61
  31. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Quicksort Schritt

    2: Implementation Demo Lars Hupel Schwarze Magie 8. September 2011 23 / 61
  32. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Werte und

    Typen Terminologie Datenkonstruktoren erzeugen Daten in Java: „Konstruktoren“ Typkonstruktoren erzeugen Typen in Java: „generische Klasse“ auch bekannt als „parametrische Polymorphie“ Lars Hupel Schwarze Magie 8. September 2011 24 / 61
  33. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Werte und

    Typen Terminologie Datenkonstruktoren erzeugen Daten in Java: „Konstruktoren“ Typkonstruktoren erzeugen Typen in Java: „generische Klasse“ auch bekannt als „parametrische Polymorphie“ Lars Hupel Schwarze Magie 8. September 2011 24 / 61
  34. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Werte und

    Typen Terminologie Datenkonstruktoren erzeugen Daten in Java: „Konstruktoren“ Typkonstruktoren erzeugen Typen in Java: „generische Klasse“ auch bekannt als „parametrische Polymorphie“ Lars Hupel Schwarze Magie 8. September 2011 24 / 61
  35. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Werte und

    Typen Terminologie Datenkonstruktoren erzeugen Daten in Java: „Konstruktoren“ Typkonstruktoren erzeugen Typen in Java: „generische Klasse“ auch bekannt als „parametrische Polymorphie“ Lars Hupel Schwarze Magie 8. September 2011 24 / 61
  36. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Werte und

    Typen Kinds „Kind“ bezeichnet die Struktur eines Typkonstruktors Notation * steht für beliebigen Typ -> steht für Abbildung Lars Hupel Schwarze Magie 8. September 2011 25 / 61
  37. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Werte und

    Typen Kinds „Kind“ bezeichnet die Struktur eines Typkonstruktors Notation * steht für beliebigen Typ -> steht für Abbildung Lars Hupel Schwarze Magie 8. September 2011 25 / 61
  38. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Werte und

    Typen Kinds „Kind“ bezeichnet die Struktur eines Typkonstruktors Notation * steht für beliebigen Typ -> steht für Abbildung Lars Hupel Schwarze Magie 8. September 2011 25 / 61
  39. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Typen und

    Kinds Beispiele Typ Deklaration Kind Liste 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
  40. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Methoden und

    Funktionen Methoden sind keine first class citizen Funktionen sind „gewöhnliche“ Objekte mit apply-Methode Methode −→ Funktion per f _ aber: Was ist mit generischen Methoden? Lars Hupel Schwarze Magie 8. September 2011 27 / 61
  41. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Methoden und

    Funktionen Methoden sind keine first class citizen Funktionen sind „gewöhnliche“ Objekte mit apply-Methode Methode −→ Funktion per f _ aber: Was ist mit generischen Methoden? Lars Hupel Schwarze Magie 8. September 2011 27 / 61
  42. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Methoden und

    Funktionen Notwendigkeit von Kinds def transform[A](opt: Option[A]): List[A] = opt.toList > transform _ res0: Option[Nothing] => List[Nothing] = <function1> Lars Hupel Schwarze Magie 8. September 2011 28 / 61
  43. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Methoden und

    Funktionen Notwendigkeit 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 } Lars Hupel Schwarze Magie 8. September 2011 29 / 61
  44. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Methoden und

    Funktionen Notwendigkeit 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 und Funktionen Lars Hupel Schwarze Magie 8. September 2011 29 / 61
  45. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Kindinferenz ...

    ist so gut wie nicht vorhanden explizite Deklaration erforderlich Inferenz der Parameter beim Aufruf einer solchen Methode schlägt oft fehl Lars Hupel Schwarze Magie 8. September 2011 30 / 61
  46. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Typäquivalenz Problem

    generische Klasse, bei der einige Methoden nur bei speziellen Typparametern angeboten werden Lars Hupel Schwarze Magie 8. September 2011 31 / 61
  47. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Typäquivalenz Problem

    generische Klasse, bei der einige Methoden nur bei speziellen Typparametern angeboten werden Lösung: impliziter „Beweis“ Lars Hupel Schwarze Magie 8. September 2011 31 / 61
  48. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Naive Implementation

    class =:=[From, To] extends (From => To) implicit def tpEquals[A] = new =:=[A, A] Disclaimer Zugriffsschutz fehlt Casten kann nicht verhindert werden Lars Hupel Schwarze Magie 8. September 2011 32 / 61
  49. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Naive Implementation

    Verwendung trait Generic[A] { val a: A def onlyForString(implicit ev: A =:= String) = a.charAt(0) } Lars Hupel Schwarze Magie 8. September 2011 33 / 61
  50. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Naive Implementation

    Nachteile aus A =:= B kann nicht B =:= A konstruiert werden aus A =:= B und B =:= C kann nicht A =:= C konstruiert werden aus A =:= B kann nicht F[A] =:= F[B] konstruiert werden keine vollständige Äquivalenz auf Typebene Lars Hupel Schwarze Magie 8. September 2011 34 / 61
  51. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Naive Implementation

    Nachteile aus A =:= B kann nicht B =:= A konstruiert werden aus A =:= B und B =:= C kann nicht A =:= C konstruiert werden aus A =:= B kann nicht F[A] =:= F[B] konstruiert werden keine vollständige Äquivalenz auf Typebene Lars Hupel Schwarze Magie 8. September 2011 34 / 61
  52. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Naive Implementation

    Nachteile aus A =:= B kann nicht B =:= A konstruiert werden aus A =:= B und B =:= C kann nicht A =:= C konstruiert werden aus A =:= B kann nicht F[A] =:= F[B] konstruiert werden keine vollständige Äquivalenz auf Typebene Lars Hupel Schwarze Magie 8. September 2011 34 / 61
  53. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Naive Implementation

    Nachteile aus A =:= B kann nicht B =:= A konstruiert werden aus A =:= B und B =:= C kann nicht A =:= C konstruiert werden aus A =:= B kann nicht F[A] =:= F[B] konstruiert werden keine vollständige Äquivalenz auf Typebene Lars Hupel Schwarze Magie 8. September 2011 34 / 61
  54. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Naive Implementation

    Nachteile aus A =:= B kann nicht B =:= A konstruiert werden aus A =:= B und B =:= C kann nicht A =:= C konstruiert werden aus A =:= B kann nicht F[A] =:= F[B] konstruiert werden keine vollständige Äquivalenz auf Typebene Lars Hupel Schwarze Magie 8. September 2011 34 / 61
  55. Ü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
  56. Ü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
  57. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Implementation mit

    Kinds Konvertierungsfunktion Wie bekommt man aus A ~ B ein A => B? Lars Hupel Schwarze Magie 8. September 2011 37 / 61
  58. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Implementation mit

    Kinds Konvertierungsfunktion 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
  59. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Implementation mit

    Kinds Konvertierungsfunktion def witness[A,B](f: A ~ B): A => B = f.subst(identity[A] _) Lars Hupel Schwarze Magie 8. September 2011 38 / 61
  60. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Implementation mit

    Kinds Konvertierungsfunktion def witness[A,B](f: A ~ B): A => B = f.subst(identity[A] _) argument expression’s type is not compatible with formal parameter type; found : A => A required: ?F[A] Lars Hupel Schwarze Magie 8. September 2011 38 / 61
  61. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Implementation mit

    Kinds Konvertierungsfunktion 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
  62. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Implementation mit

    Kinds Inversion 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
  63. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Implementation mit

    Kinds Lifting 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
  64. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Heterogeneous Lists

    Problem Funktionen mit mehreren Rückgabewerten Standardlösung: Verwendung von Tupeln Lars Hupel Schwarze Magie 8. September 2011 42 / 61
  65. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Heterogeneous Lists

    Nachteile von Tupeln in Scala: jede Stelligkeit eigene Klasse begrenzte Stelligkeit Lars Hupel Schwarze Magie 8. September 2011 43 / 61
  66. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Heterogeneous Lists

    Nachteile von Tupeln in Scala: jede Stelligkeit eigene Klasse begrenzte Stelligkeit Lösung: Heterogeneous Lists (statisch typisierte) Listen mit uneinheitlichen Elementtypen Lars Hupel Schwarze Magie 8. September 2011 43 / 61
  67. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Heterogeneous Lists

    Nachteile von Tupeln in Scala: jede Stelligkeit eigene Klasse begrenzte Stelligkeit Lösung: Heterogeneous Lists (statisch typisierte) Listen mit uneinheitlichen Elementtypen Lars Hupel Schwarze Magie 8. September 2011 43 / 61
  68. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Implementation sealed

    trait HList final case class HCons[H, T <: HList]( head: H, tail: T ) extends HList { def ::[T](v: T) = HCons(v, this) } case object HNil extends HList { def ::[T](v: T) = HCons(v, this) } Lars Hupel Schwarze Magie 8. September 2011 44 / 61
  69. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Verwendung Erzeugung

    > def getValues = 3 :: "foo" :: HNil getValues: HCons[Int,HCons[String,HNil.type]] > getValues res0: HCons[...] = HCons(3,HCons(foo,HNil)) Lars Hupel Schwarze Magie 8. September 2011 45 / 61
  70. Ü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
  71. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Verwendung Indexbasierter

    Zugriff eine Funktion HList[H, T] => Int => Any möglich, aber nicht hilfreich Idee: index-Funktion muss einen Typparameter haben, der die Position in der Liste repräsentiert Lösung: Peano-Numerale Lars Hupel Schwarze Magie 8. September 2011 47 / 61
  72. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Verwendung Indexbasierter

    Zugriff eine Funktion HList[H, T] => Int => Any möglich, aber nicht hilfreich Idee: index-Funktion muss einen Typparameter haben, der die Position in der Liste repräsentiert Lösung: Peano-Numerale Lars Hupel Schwarze Magie 8. September 2011 47 / 61
  73. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Peano-Numerale Wertbasiert

    trait Nat case object Zero case class Succ(n: Nat) val two = Succ(Succ(Zero)) Lars Hupel Schwarze Magie 8. September 2011 48 / 61
  74. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Peano-Numerale Typbasiert

    trait Nat trait Zero extends Nat trait Succ[N <: Nat] extends Nat type Two = Succ[Succ[Zero]] Lars Hupel Schwarze Magie 8. September 2011 49 / 61
  75. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Peano-Numerale und

    HLists Zugriffstrait trait AccessN[L <: HList, N <: Nat, R] { def apply(l: L): R } Lars Hupel Schwarze Magie 8. September 2011 50 / 61
  76. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Peano-Numerale und

    HLists HCons revisited case class HCons[H, T <: HList](head: H, tail: T) extends HList { def apply[N <: Nat, R](n: N) (implicit access: AccessN[HCons[H, T], N, R]) = access(list) } Lars Hupel Schwarze Magie 8. September 2011 51 / 61
  77. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Peano-Numerale und

    HLists Implementation implicit def accessZero[H, T <: HList] = new AccessN[HCons[H, T], Zero, H] { def apply(l: HCons[H, T]) = l.head } implicit def accessN[H, T <: HList, N <: Nat, R] (implicit accessTail: AccessN[T, N, R]) = new AccessN[HCons[H, T], Succ[N], R] { def apply(l: HCons[H, T]) = accessTail(l.tail) } Lars Hupel Schwarze Magie 8. September 2011 52 / 61
  78. Ü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
  79. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Peano-Numerale und

    HLists Verwendung val _0 = new Zero {} val _1 = new Succ[Zero] {} val _2 = ... Lars Hupel Schwarze Magie 8. September 2011 54 / 61
  80. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Peano-Numerale und

    HLists Verwendung > 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
  81. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Heterogeneous Lists

    Vorteile Verwalten von verschiedenen Typen, ohne eine Klasse anlegen zu müssen Tupel beliebiger Stelligkeit kein Verlust von Typinformationen verglichen mit List[Any] Compiler kann falsche Verwendung erkennen dank Scalas Syntaxzucker „fühlen“ sich HLists wie normale Listen an sind auch in Java möglich, aber viel Overhead nötig Lars Hupel Schwarze Magie 8. September 2011 56 / 61
  82. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Anwendung Problem:

    Signatur von String.format stellt nicht sicher, dass die Argumente zum Formatstring passen Compiler kann Fehler nicht aufspüren Idee: Funktion konstruieren, die eine HList von den Argumenten nimmt und diese formatiert Lars Hupel Schwarze Magie 8. September 2011 57 / 61
  83. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Anwendung Problem:

    Signatur von String.format stellt nicht sicher, dass die Argumente zum Formatstring passen Compiler kann Fehler nicht aufspüren Idee: Funktion konstruieren, die eine HList von den Argumenten nimmt und diese formatiert Lars Hupel Schwarze Magie 8. September 2011 57 / 61
  84. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Typsicheres printf

    Implementation Demo Lars Hupel Schwarze Magie 8. September 2011 58 / 61
  85. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Typsicheres printf

    Vorteile Compiler kann Formatierung prüfen weniger Exceptions selbst definierte Operatoren erhöhen (richtig eingesetzt) die Lesbarkeit Lars Hupel Schwarze Magie 8. September 2011 59 / 61
  86. Überblick Dependent types Collections Kinds Typäquivalenz Heterogeneous Lists Typsicheres printf

    Nachteile gezeigte Lösung vereinfacht, benötigt noch Tricks zum Laufen Fehlermeldungen können sehr unübersichtlich werden „Denken in Typen“ erfordert in der Regel einige Eingewöhnung Lars Hupel Schwarze Magie 8. September 2011 60 / 61