Geneeriset tyypit TIES542 Ohjelmointikielten periaatteet, kevät 2007 Antti-Juhani Kaijanaho Jyväskylän yliopisto Tietotekniikan laitos 6. maaliskuuta 2007
Kysymys Mitä yhteistä on seuraavilla funktioilla? isnilint = λx : µt. nil : (), cons : (int, t).case x of nil true, cons false isnilfloat = λx : µt. nil : (), cons : (float, t).case x of nil true, cons false Vastaus Ne ovat sama funktio, vain tyypit ovat tiellä! Kysymys Hylätäänkö tyypit? Vastaus Voisi niinkin tehdä, mutta katsotaan ensin, saadaanko tämä korjattua!
Idea! Otetaan tyyppi parametriksi! isnil = Λt 1.λx : µt 2. nil : (), cons : (t 1, t 2).case x of nil true, cons false isnilint = isnil[int] isnilfloat = isnil[float] Onnistuuko? No totta kai!
Systeemi F: (Abstrakti) syntaksi E ::= I (lauseke)muuttuja E 1 E 2 applikaatio λi : T.E abstraktio E[T ] tyyppiapplikaatio ΛI.E tyyppiabstraktio T ::= I tyyppimuuttuja T 1 T 2 funktiotyyppi I.T universaali tyyppi Γ := Γ, I : T Γ, I
Systeemi F: Tyypityssäännöt Γ, I : T I : T Γ E 1 : T 1 T 2 Γ E 2 : T 1 Γ E 1 E 2 : T 2 I Γ Γ, I : T 1 E : T 2 Γ λi : T 1.E : T 1 T 2 (I, T ) Γ Γ, I E : T (I, T ) Γ : I ei esiinny vapaana T :ssa Γ ΛI.E : I.T Γ E : ΛI.T 1 Γ E[T 2] : T 1[I := T 2]
Systeemi F: Laskentasäännöt Samat säännöt kuin yksinkertaisesti tyypitetyssä λ-laskennossa. Lisäksi seuraavat: E E E[T ] E [T ] (ΛI.E)[T ] E [I := T ]
Esimerkkejä 1. (ΛX.λx : X.x) : X.X X 2. (ΛX.λx : X.x)[Int] (λx : Int.x) 3. (λx : ( X : X X ).x[ X.X X ] x) : ( X.X X ) ( X.X X )
Määritelmä (Kumitus) Määritellään funktio erase Systeemi F:n lausekkeista tyypittömän λ-laskennon lausekkeille seuraavasti: erase(i ) = I erase(λi : T.E) = λi.e erase(e 1 E 2 ) = erase(e 1 ) erase(e 2 ) erase(λi.e) = λi. erase(e) erase(e[t ]) = erase(e) (λx.x) I uusi Tätä funktiota sanotaan tyyppien kumitukseksi (engl. type erasure, turkulaisittain tyyppitypistys).
Lause Olkoon ( F ) Systeemi F:n laskentarelaatio ja olkoon ( λ ) tyypittömän λ-laskennon laskentarelaatio. 1 Olkoot lisäksi E ja E Systeemi F:n lausekkeita. Tällöin, jos E F E niin erase(e) λ erase(e ). Todistus. Jääköön jokaisen itse mietittäväksi. Huomautus Kumitus voidaan muotoilla yksinkertaisillekin tyypeille siten, että vastaava lause pätee. Huomautus Kumitus osoittaa, että Systeemi F:n (ja yksinkertaisten tyyppien) laskenta on tyypeistä riippumatonta. 1 Näitä on toki molemmissa useita, mutta valitaan toisiaan vastaavat, esim. molemmissa normaalijärjestys tai molemmissa β-muunnos.)
Esimerkki Olkoon meillä tyyppi List t kaikilla tyypeillä t. Joitakin sen käsittelyssä hyödyllisiä funktioita ovat: empty : t.list t prepend : t.t List t List t isempty : t.list t Bool first : t.list t t rest : t.list t List t Näiden avulla voidaan kirjoittaa funktio map : t. u.(t u) List t List u seuraavasti: map = Λt.Λu.λf : (t u).λs : List t.fix(λm : (List t List u). if isempty[t] s then empty[u] else prepend[u](f (first[t] s))(m (rest[t] s)))
Kysymys List t ei ole Systeemi F:n tyyppi! Voiko tämän korjata? Vastaus List on tyyppitoimitus (engl. type operator), tyyppitasolla toimiva funktio (eli siis funktio tyypeiltä tyypeille. Lisäämällä Systeemi F:ään tyyppitoimitukset, saadaan Systeemi F ω.
Systeemi F ω lisätään tyyppeihin tuki abstraktiolle ja applikaatiolle List = λt.µs. nil : (), cons : (t, s) jotta tyyppijärjestelmä olisi ratkeava (engl. decidable), tulee tyypeillä olla tyypit engl. kinds, suomennetaan vaikka luonteet luonne : tavalliset tyypit luonne : yksinkertaiset tyyppitoimitukset tyyppilausekkeella T on luonne K merkitään T :: K List :: ns. korkean kertaluokan tyyppitoimitukset ovat varsin esoteerisia luonteiltaan esim. ( ) esim. Haskellin monadit nyt viimeistään on pakko tehdä tyyppiyhtäläisyydestä eksplisiittistä
Systeemi F ω : (Abstrakti) syntaksi E ::= I (lauseke)muuttuja E 1 E 2 applikaatio λi : T.E abstraktio E[T ] tyyppiapplikaatio ΛI :: K.E tyyppiabstraktio T ::= I tyyppimuuttuja T 1 T 2 funktiotyyppi I :: K.T universaali tyyppi T 1 T 2 tyyppitason applikaatio λi :: K.T tyyppitason abstraktio K ::= tavallisen tyypin luonne K 1 K 2 tyyppitoimitusluonne Γ := Γ, I : T Γ, I :: T
Systeemi F ω : Luonnehdintasäännöt Γ, I :: K I :: K Γ, I :: K 1 T :: K 2 Γ (λi :: K 1.T ) :: K 1 K 2 Γ T 1 :: K 1 K 2 Γ T 2 :: K 1 Γ T 1 T 2 :: K 2 Γ T 1 :: Γ T 2 :: Γ T 1 T 2 :: Γ, I :: K T :: Γ ( I :: K.T ) ::
Systeemi F ω : Tyyppiyhtäläisyys T T T 2 T 1 T 1 T 2 T 1 T 2 T 2 T 3 T 1 T 3 T 1 T 1 T 2 T 2 T 1 T 2 T 1 T 2 T 1 T 2 I : K.T 1 I : K.T 2 T 1 T 1 T 2 T 2 T 1 T 2 T 1 T 2 (λi :: K.T 1) T 2 T 1[I := T 2]
Systeemi F ω : Tyypityssäännöt Γ, I : T I : T Γ E 1 : T 1 T 2 Γ E 2 : T 1 Γ E 1 E 2 : T 2 (I, K) Γ Γ T 1 :: Γ, I : T 1 E : T 2 Γ λi : T 1.E : T 1 T 2 (I, T ) Γ Γ, I :: K E : T (I, T ) Γ : I ei esiinny vapaana T :ssa Γ ΛI :: K.E : I :: K.T Γ E : ΛI :: K.T 1 Γ T 2 :: K Γ E[T 2] : T 1[I := T 2] Γ E : T Γ T :: T T Γ E : T
Systeemi F ω : Laskentasäännöt Samat säännöt kuin yksinkertaisesti tyypitetyssä λ-laskennossa. Lisäksi seuraavat: E E E[T ] E [T ] (ΛI :: K.E)[T ] E [I := T ]
Once more unto the breach lisätään Systeemi F ω :aan alityypitys idea: tyyppikvantifiointi on rajoittunutta voidaan sanoa vaikkapa, että jokin funktio toimii geneerisesti vain tietyn tyypin alityypeillä periaatteessa voidaan rajoittaa myös tyyppitoimituksia, mutta jätetään se nyt väliin
Systeemi F ω <: (Abstrakti) syntaksi E ::= I (lauseke)muuttuja E 1 E 2 applikaatio λi : T.E abstraktio E[T ] tyyppiapplikaatio ΛI <: T.E tyyppiabstraktio T ::= I tyyppimuuttuja T 1 T 2 funktiotyyppi I <: K.T universaali tyyppi T 1 T 2 tyyppitason applikaatio λi :: K.T tyyppitason abstraktio Top kansityyppi K ::= tavallisen tyypin luonne K 1 K 2 tyyppitoimitusluonne Γ ::= Γ, I : T Γ, I <: T
Systeemi F ω <: Yleistetty Top Määritelmä Määritellään lyhennysmerkintä rekursiivisesti: Top[ ] = Top Top[K 1 K 2] = ΛI :: K 1.Top[K 2] I uusi Väite Γ T <: Top[K] jos ja vain jos Γ T :: K. Todistus. Induktiolla, sivuutetaan.
Systeemi F ω <: Luonnehdintasäännöt Γ T :: K Γ, I <: T I :: K Γ Top :: Γ, I <: Top[K 1] T :: K 2 Γ (λi :: K 1.T ) :: K 1 K 2 Γ T 1 :: K 1 K 2 Γ T 2 :: K 1 Γ T 1 T 2 :: K 2 Γ T 1 :: Γ T 2 :: Γ T 1 T 2 :: Γ, I <: T 1 T 2 :: Γ ( I <: T 1.T 2) ::
Systeemi F ω <: Tyyppiyhtäläisyys T T T 2 T 1 T 1 T 2 T 1 T 2 T 2 T 3 T 1 T 3 T 1 T 1 T 2 T 2 T 1 T 2 T 1 T 2 U 1 U 2 T 1 T 2 I <: U 1.T 1 I <: U 2.T 2 T 1 T 1 T 2 T 2 T 1 T 2 T 1 T 2 (λi :: K.T 1) T 2 T 1[I := T 2]
Systeemi F ω <: Alityypitys Γ T 1 <: T 2 Γ T 2 <: T 3 Γ T 1 <: T 3 Γ T :: Γ T 1 <: Top Γ T 1 <: T 1 Γ T 2 <: T 2 Γ T 1 T 2 <: T 1 T 2 Γ, I <: T I <: T Γ T 1 :: K Γ, I <: T 1 T 2 <: T 2 Γ ( I <: T 1.T 2) <: ( I <: T 1.T 2) Γ, I <: Top[K] T 1 <: T 2 Γ (λi :: K.T 1) <: (λi :: K.T 2) Γ T 1 <: T 2 Γ T 1 T 2 <: T 1 T 2 Γ T 1 :: K Γ T 2 :: K T 1 T 2 Γ T 1 <: T 2
Systeemi F ω <: Tyypityssäännöt Γ, I : T I : T Γ E 1 : T 1 T 2 Γ E 2 : T 1 Γ E 1 E 2 : T 2 (I, K) Γ Γ T 1 :: Γ, I : T 1 E : T 2 Γ λi : T 1.E : T 1 T 2 (I, T ) Γ Γ, I <: U E : T (I, T ) Γ : I ei esiinny vapaana T :ssa Γ ΛI <: U.E : I <: U.T Γ E : ΛI <: U.T 1 Γ T 2 <: U Γ E[T 2] : T 1[I := T 2] Γ E : T Γ T :: T <: T Γ E : T
Systeemi F ω <: Laskentasäännöt Samat säännöt kuin yksinkertaisesti tyypitetyssä λ-laskennossa. Lisäksi seuraavat: E E E[T ] E [T ] (ΛI <: U.E)[T ] E [I := T ]