Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Typy generyczne wy˙zszych rz ˛edów
Zagadnienia Programowania Obiektowego
Piotr Wojnarowski
Wydział Matematyki, Informatyki i Mechaniki Uniwersytet Warszawski
26.04.2010
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Spis tre´sci
1 Wprowadzenie do generyczno´sci Typy generyczne pierwszego rz ˛edu Typy generyczne wy˙zszych rz ˛edów
2 Typy generyczne wy˙zszych rz ˛edów w Scali Podtypy
Rodzaje- kinds Implicits
3 Podsumowanie
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Generics of a Higher Kind, OOPSLA 2008
Adriaan Moors, Frank Piessens- Katolicki Uniwersytet w Leuven
Martin Oderksy- Ecole Politechnic w Lozannie
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Typy generyczne pierwszego rz ˛edu Typy generyczne wy˙zszych rz ˛edów
Typy generyczne pierwszego rz ˛edu
Czym s ˛a typy generyczne (uogólnione)?
Klasyczny przykład: List<T>
Dost ˛epne nie od dzi´s w wielu j ˛ezykach programowania:
j ˛ezyki funkcyjne, Java, C#, C++
Uogólnienie kodu, niezale˙znie od klas, redukcja duplikacji kodu
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Typy generyczne pierwszego rz ˛edu Typy generyczne wy˙zszych rz ˛edów
Kilka definicji
Typ konkretny, np: List[Int]
Konstruktor typu uogólnionego, np: List Deklaracja typu uogólnionego, np: List[T]
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Typy generyczne pierwszego rz ˛edu Typy generyczne wy˙zszych rz ˛edów
A gdyby mo˙zna było uogólni´c bardziej?
Przyład
t r a i t I t e r a b l e [ T ] {
d e f f i l t e r ( p : T => Boolean ) : I t e r a b l e [ T ] d e f remove ( p : T => Boolean ) : I t e r a b l e [ T ] = f i l t e r ( x => ! p ( x ) )
}
t r a i t L i s t [ T ] extends I t e r a b l e [ T ] { d e f f i l t e r ( p : T => Boolean ) : L i s t [ T ]
o v e r r i d e d e f remove ( p : T => Boolean ) : L i s t [ T ] = f i l t e r ( x => ! p ( x ) )
}
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Typy generyczne pierwszego rz ˛edu Typy generyczne wy˙zszych rz ˛edów
Mo˙zna! (W Scali)
Przyład
t r a i t I t e r a b l e [ T , C o n t a i n e r [ X ] ] {
d e f f i l t e r ( p : T => Boolean ) : C o n t a i n e r [ T ] d e f remove ( p : T => Boolean ) : C o n t a i n e r [ T ] =
f i l t e r ( x => ! p ( x ) ) }
t r a i t L i s t [ T ] extends I t e r a b l e [ T , L i s t ]
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Typy generyczne pierwszego rz ˛edu Typy generyczne wy˙zszych rz ˛edów
Typy wy˙zszych rz ˛edów w skrócie
Mo˙zemy mie´c uogólnione konstruktory typów Jak wida´c, pozwala to na dalsz ˛a redukcj ˛e kodu Dost ˛epne w j ˛ezykach takich jak Haskell czy Scala
Praktyczne zastosowania: list comprehensions (budowanie list na podstawie innych list, operator yield), kombinatory parserów, j ˛ezyki dziedzinowe (DSL)
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Podtypy Rodzaje- kinds Implicits
Krótkie przypomnienie składni
trait- interface + mixin object- singleton, jak klasa pola typów (type members):
Type member
t r a i t L i s t { t y p e T }
L i s t { t y p e T= I n t }
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Podtypy Rodzaje- kinds Implicits
Dalsze mo˙zliwo´sci
Ograniczanie parametrów:
Iterowalna kolekcja
t r a i t I t e r a b l e [ T ] {
t y p e C o n t a i n e r [ X ] <: I t e r a t o r [ T ] }
Analogicznie >:
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Podtypy Rodzaje- kinds Implicits
In-, ko- i kontrawariancja
Typy uogólnione nie musz ˛a „dziedziczy´c” w zwykłej kolejno´sci Stack[T] jest podtypem Stack[S] wtw S == T
Stack[+T] jest podtypem Stack[S] wtw S >: T Stack[-T] jest podtypem Stack[S] wtw S <: T
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Podtypy Rodzaje- kinds Implicits
Rodzaje- schemat
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Podtypy Rodzaje- kinds Implicits
Po co rodzaje?
Rodzaje- konstrukcja niedost ˛epna dla programisty, u˙zyta na poziomie kompilatora
*- warto´sci
-> - konstruktor typów, klasyfikuje konstruktory typów
* (T, U) - typ o dolnym ograniczeniu T i górnym U
Nothing, Any- domy´slne warto´sci dla T i U, * (Nothing, Any)
== *, *(Nothing, U) == * (U)
Container[X] <: Iterable[X] == X @ * -> * (Iterable[X]) Pod- rodzaje: * (T, U) <: * (T’, U’) wtw gdy T’ <: T i U <: U’
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Podtypy Rodzaje- kinds Implicits
Po co rodzaje, przykład
Iterowalna lista numeryczna
c l a s s I t e r a b l e [ C o n t a i n e r [ X ] , T ]
t r a i t N u m e r i c L i s t [ T <: Number ] extends I t e r a b l e [ N u m e r i c L i s t , T ]
Bł ˛ad podczas kompilacji! Dlaczego?
NumericList: * (Number) -> * Container: * -> *
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Podtypy Rodzaje- kinds Implicits
Po co rodzaje, przykład
Iterowalna lista numeryczna
c l a s s I t e r a b l e [ C o n t a i n e r [ X ] , T ]
t r a i t N u m e r i c L i s t [ T <: Number ] extends I t e r a b l e [ N u m e r i c L i s t , T ]
Bł ˛ad podczas kompilacji! Dlaczego?
NumericList: * (Number) -> * Container: * -> *
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Podtypy Rodzaje- kinds Implicits
Po co rodzaje, poprawnie
Iterowalna, ograniczona lista
c l a s s I t e r a b l e [ C o n t a i n e r [ X <: Bound ] , T <: Bound , Bound ]
t r a i t N u m e r i c L i s t [ T <: Number ] extends I t e r a b l e [ N u m e r i c L i s t , T , Number ]
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Podtypy Rodzaje- kinds Implicits
Parametry domniemane
implicits
t r a i t Ord [ T ] {
d e f <= ( o t h e r : T ) : Boolean }
i m p o r t j a v a . u t i l . Date
i m p l i c i t d e f dateAsOrd ( s e l f : Date )
= new Ord [ Date ] {
d e f <= ( o t h e r : Date ) = s e l f . e q u a l s ( o t h e r )
| | s e l f . b e f o r e ( o t h e r ) }
d e f max [ T <% Ord [ T ] ] ( x : T , y : T ) : T
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Ograniczenia
Czego nie da si ˛e zrobi´c w Scali?
Cz ˛e´sciowa aplikacja parametrów typów Funkcje anonimowe z typami uogólnionymi Currying
Brak interfejsu typów dla typów uogólnionych wy˙zszych rz ˛edów
Przynajmniej na razie
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Podsumowanie
Redukcja duplikacji kodu w bibliotekach wykorzystuj ˛acych typy uogólnione
Łatwiejsze u˙zywanie takich bibliotek, np. nie trzeba rzutowa´c kolekcji otrzymanej z filter() na ˙z ˛adany typ Sprzyjaj ˛a pisaniu bilioteki z ich u˙zyciem tak, ˙zeby u˙zytkownik nawet nie wiedział o ich zastosowaniu, ale zauwa˙zył łatwiejsz ˛a obsług ˛e
Wprowadzenie do generyczno´sci Typy generyczne wy˙zszych rz ˛edów w Scali Podsumowanie
Koniec
Dzi ˛ekuj ˛e