TIES542 kevät 2009 Tyyppijärjestelmän laajennoksia

Samankaltaiset tiedostot
TIES542 kevät 2009 Rekursiiviset tyypit

14.1 Rekursio tyypitetyssä lambda-kielessä

tään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla

Haskell ohjelmointikielen tyyppijärjestelmä

Geneeriset tyypit. TIES542 Ohjelmointikielten periaatteet, kevät Antti-Juhani Kaijanaho. Jyväskylän yliopisto Tietotekniikan laitos

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Ydin-Haskell Tiivismoniste

Alityypitys. TIES542 Ohjelmointikielten periaatteet, kevät Antti-Juhani Kaijanaho. Jyväskylän yliopisto Tietotekniikan laitos

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 30. marraskuuta 2015

TIES542 kevät 2009 Tyyppiteorian alkeet

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

Yksinkertaiset tyypit

Laajennetaan vielä Ydin-Haskellia ymmärtämään vakiomäärittelyt. Määrittely on muotoa

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005

11/20: Konepelti auki

Oliot ja tyypit. TIES542 Ohjelmointikielten periaatteet, kevät Antti-Juhani Kaijanaho. Jyväskylän yliopisto Tietotekniikan laitos

Tietueet. Tietueiden määrittely

Demo 7 ( ) Antti-Juhani Kaijanaho. 9. joulukuuta 2005

Koka. Ryhmä 11. Juuso Tapaninen, Akseli Karvinen. 1. Taustoja 2. Kielen filosofia ja paradigmat 3. Kielen syntaksia ja vertailua JavaScriptiin Lähteet

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Staattinen tyyppijärjestelmä

lausekkeiden tapauksessa. Jotkin ohjelmointikielet on määritelty sellaisiksi,

ELM GROUP 04. Teemu Laakso Henrik Talarmo

Tyyppiluokat II konstruktoriluokat, funktionaaliset riippuvuudet. TIES341 Funktio-ohjelmointi 2 Kevät 2006

TIES542 kevät 2009 Oliokielten erityispiirteitä

sama tyyppi (joka vastaa kaikkien mahdollisten arvojen summa-aluetta). Esimerkiksi

Osoitin ja viittaus C++:ssa

TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 26. kesäkuuta 2013

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 3. lokakuuta 2016

AS C-ohjelmoinnin peruskurssi 2013: C-kieli käytännössä ja erot Pythoniin

Groovy. Niko Jäntti Jesper Haapalinna Group 31

4. Luokan testaus ja käyttö olion kautta 4.1

2) Aliohjelma, jonka toiminta perustuu sivuvaikutuksiin: aliohjelma muuttaa parametrejaan tai globaaleja muuttujia, tulostaa jotakin jne.

Lisää laskentoa. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Ohjelmointi 2. Jussi Pohjolainen. TAMK» Tieto- ja viestintäteknologia , Jussi Pohjolainen TAMPEREEN AMMATTIKORKEAKOULU

2.4 Normaalimuoto, pohja ja laskentajärjestys 2.4. NORMAALIMUOTO, POHJA JA LASKENTAJÄRJESTYS 13

tietueet eri tyyppisiä tietoja saman muuttujan arvoiksi

Kielioppia: toisin kuin Javassa

Taulukot. Jukka Harju, Jukka Juslin

Attribuuttikieliopit

Luku 5. Monadit. 5.1 Siirrännän ongelma

Imperatiivisen ohjelmoinnin peruskäsitteet. Meidän käyttämän pseudokielen lauseiden syntaksi

Java-kielen perusteet

TIEA241 Automaatit ja kieliopit, kevät Antti-Juhani Kaijanaho. 12. kesäkuuta 2013

Tieto- ja tallennusrakenteet

TIEA241 Automaatit ja kieliopit, kevät 2011 (IV) Antti-Juhani Kaijanaho. 16. toukokuuta 2011

Ohjelmoinnin perusteet Y Python

7/20: Paketti kasassa ensimmäistä kertaa

Tietorakenteet ja algoritmit - syksy

Ohjelmointikieli TIE Principles of Programming Languages Syksy 2017 Ryhmä 19

5.5 Jäsenninkombinaattoreista

Luku 15. Parametripolymorfismi Kumitus

vaihtoehtoja TIEA241 Automaatit ja kieliopit, syksy 2016 Antti-Juhani Kaijanaho 13. lokakuuta 2016 TIETOTEKNIIKAN LAITOS

Rekursiiviset palautukset [HMU 9.3.1]

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen

TIE Principles of Programming Languages. Seminaariesityksen essee. Ryhmä 18: Heidi Vulli, Joni Heikkilä

Jakso 4 Aliohjelmien toteutus

Abstraktit tietotyypit. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

Tämän vuoksi kannattaa ottaa käytännöksi aina kirjoittaa uuden funktion tyyppi näkyviin, ennen kuin alkaa sen määritemää kirjoittamaan.

TIE Principles of Programming Languages CEYLON

15. Ohjelmoinnin tekniikkaa 15.1

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 16. marraskuuta 2015

jäsentäminen TIEA241 Automaatit ja kieliopit, syksy 2015 Antti-Juhani Kaijanaho 26. marraskuuta 2015 TIETOTEKNIIKAN LAITOS

samalla seuraavaan puoliavaruuteen (sukupolveen), jota siivotaan harvemmin.

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista

Algoritmit 1. Luento 3 Ti Timo Männikkö

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 3. joulukuuta 2015

1. Omat operaatiot 1.1

TIEA241 Automaatit ja kieliopit, kevät Antti-Juhani Kaijanaho. 16. helmikuuta 2012

58131 Tietorakenteet ja algoritmit (syksy 2015)

ITKP102 Ohjelmointi 1 (6 op)

Säännöllisten kielten sulkeumaominaisuudet

Tutoriaaliläsnäoloista

815338A Ohjelmointikielten periaatteet Harjoitus 4 vastaukset

Concurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo

TIEA241 Automaatit ja kieliopit, kevät Antti-Juhani Kaijanaho. 26. tammikuuta 2012

Rekursiiviset tyypit

Luento 4 Aliohjelmien toteutus

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

1. Miten tehdään peliin toinen maila?

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2

4.2. ALIOHJELMAT 71. Tulosvälitteisyys (call by result) Tulosvälitteinen parametri kopioidaan lopuksi

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014

Se mistä tilasta aloitetaan, merkitään tyhjästä tulevalla nuolella. Yllä olevassa esimerkissä aloitustila on A.

1 Tavoitteet. 2 Periaatteet ja ominaisuudet. 2.1 Tyyppipäättely

TIEA241 Automaatit ja kieliopit, kevät 2011 (IV) Antti-Juhani Kaijanaho. 19. tammikuuta 2012

Ohjelmointi 1 / syksy /20: IDE

Lisää pysähtymisaiheisia ongelmia

TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 29. toukokuuta 2013

Hohde Consulting 2004

jäsennyksestä TIEA241 Automaatit ja kieliopit, syksy 2016 Antti-Juhani Kaijanaho 29. syyskuuta 2016 TIETOTEKNIIKAN LAITOS Kontekstittomien kielioppien

TIES542 kevät 2009 Denotaatio

Ohjelmoinnin peruskurssien laaja oppimäärä

811120P Diskreetit rakenteet

Apuja ohjelmointiin» Yleisiä virheitä

2. Lisää Java-ohjelmoinnin alkeita. Muuttuja ja viittausmuuttuja (1/4) Muuttuja ja viittausmuuttuja (2/4)

Transkriptio:

TIES542 kevät 2009 Tyyppijärjestelmän laajennoksia Antti-Juhani Kaijanaho 16. helmikuuta 2009 Tyypitetyt ohjelmointikielet sisältävät paljon muitakin konstruktioita kuin yksinkertaisesti tyypitetyn lambda-kielen, vaikka ne tyypillisesti sisältävät senkin (ainakin rajoitettuna versiona). Monisteen päälähde on Pierce (2002). 1 Yksikkötyyppi Kielissä, jotka sallivat globaalit sivuvaikutukset (kuten esimerkiksi siirrännän), on usein tarpeen kirjoittaa aliohjelmia, joilla ei ole (mielenkiintoista) paluuarvoa. C-sukuisissa kielissä kuten C, C++ ja Java tällaiseen käyttöön on varattu voidtyyppi, joka näiden kielten perinteen mukaan ei sisällä yhtään arvoa pidän tätä perinteistä näkemystä virheellisenä (tyyppiä, jossa ei ole arvoa, oleva lauseke ei voi tyyppiteorian näkökulmasta koskaan tulla lasketuksi loppuun). Tyyppiteoriassa sama ajatus mallinnetaan yksikkötyypillä (engl. unit type), jossa on yksi arvo. Kun tyypissä on yksi arvo ja jos staattinen tyyppijärjestelmä on eheä tarvitaan arvon esittämiseen log 2 1 eli nolla bittiä. Tyypistä ja sen arvosta käytetään toisinaan notaatiota Unit ja unit, toisinaan kummastakin notaatiota (). Jälkimmäinen toimii mainiosti yhteen myöhemmin esiteltävien monikkotyyppien kanssa. T, U ::= () t, u ::= () w ::= () 1

Yksikkötyypillä ei ole laskentasääntöjä. Γ () : () 2 Paikalliset muuttujat Useimmissa aliohjelmia tukevissa kielissä on tuki myös paikallisille muuttujille muuttujille, jotka näkyvät vain aliohjelmassa tai sen osassa. Tyypillinen rakenne on Pascalin var x : real begin end taikka C90:n {double x; }. Lambda-kielessä (ja siten tyyppiteoriassa) muuttujiin ei voi sijoittaa, vaan niille täytyy antaa alkuarvo heti kättelyssä. Lambda-kielen paikallisia muuttujia luova laajennus on ns. let-lauseke: t, u ::= let x = t in u Laskentasäännöstöjä let-lausekkeelle voidaan antaa kahdenlaisia. Ensimmäinen on innokkaasti laskeva joka vastaa useimpien kielien toimintatapaa: Toinen on laiskasti laskeva: Tyypityssääntö on yksinkertainen: let x = v in u u[x := v] t t let x = t in u let x = t in u let x = t in u u[x := t] Γ t : T Γ, x : T u : U Γ let x = t in u : U Jos tyypitys jätettäisiin huomiotta, let-lauseke voitaisiin ymmärtää beeta-redeksinä: let x = t in; u = (λxu)t. Yksinkertaisten tyyppien kanssa vastaavuus ei ole yhtä yksiselitteinen, sillä let-lausekkeessa ei ole tarpeen kertoa muuttujan tyyppiä, kun taas abstraktiossa se vaaditaan. Let-lauseke voidaan yleistää hyväksymään useita muuttujien määrittelyjä tyyliin let x 1 = t 1 ; x 2 = t 2 in u. Tässä on kuitenkin tehtävä valinta sen mukaan, näkyvätkö määriteltävät muuttujat muissa määritelmissä (taikka omassa määritelmässään) vai ei toisin sanoen, sallitaanko (keskenään) rekursiiviset määritelmät 2

vaiko ei. Tavanomainen let-lauseke ei tavallisesti rekursiota salli, ja tällöin se voidaankin ymmärtää kielioppimakeisena, joka tarkoittaa sisäkkäisiä yksinkertaisia let-lausekkeita: (let x 1 = t 1 ; x 2 = t 2 in u) = (let x 1 = t 1 in let x 2 = t 2 in u). Toisinaan rekursio sallitaan tällöin puhutaan ns. letrec-lausekkeesta. 3 Monikot Yksi ohjelmoinnin tärkeimmistä työkaluista on rakenteiset arvot ja niitä vastaavat rakenteiset tyypit toisin sanoen säilöt containers. Yksinkertaisin esimerkki on monikko (engl. tuple), jossa on sisällä järjestykseen asetettuna kaksi tai useampaa eri tyyppistä arvoa, joita päästään käsittelemään järjestysnumeron avulla. Monikossa on kuitenkin aina staattisesti tiedossa komponenttien lukumäärä ja tyyppi sekä mitä komponenttia ollaan kulloinkin hakemassa. Monikot sinänsä eivät ole kovin yleisiä ohjelmointikielissä, mutta niitä käytetään usein auttamaan tiettyjen konstruktioiden hahmottamisessa. Esimerkiksi moniparametrinen funktio voidaan ymmärtää toisaalta curry attyna yksiparametrisena funktiona, joka palauttaa funktion, mutta toisaalta myös (ja tavallisemmin) yksiparametrisena funktiona, jonka parametri on monikko. Samoin monen arvon palauttaminen (mikä on mahdollista joissakin kielissä) voidaan ymmärtää monikon palauttamisena. Monikon konstruointisyntaksina käytetään lähes aina sulkeita ja pilkkuja: (1, kissa, 3) toisinaan kulmasulkeita ja pilkkuja: (1, kissa, 3). Arvojen käsittelyyn voidaan määritellä projisointioperaattoreita, mutta hyödyllisempää mielestäni on laajentaa let-lausekkeen muuttujakäsitystä seuraavaan tapaan: T, U ::= (T 1,..., T n ) n 2 t, u ::= (t 1,..., t n ) n 2 let (x 1,..., x n ) = t in u n 2 w ::= (v 1,..., v n ) n 2 Γ t 1 : T 1 Γ t n : T n Γ (t 1,..., t n ) : (T 1,..., T n ) Γ t : (T 1,... T m ) Γ, x 1 : T 1,..., x n : T n u : U i j x i x j n = m Γ let (x 1,..., x n ) = t in u : U t k t k (t 1,..., t k,..., t n ) (t 1,..., t k,..., t n ) 3

t t let (x 1,..., x n ) = t in u let (x 1,..., x n ) = t in u z 1,..., z n uusia i j x i x j n = m let (x 1,..., x n ) = (v 1,..., v m ) in u u[x 1 := z 1 ] [x n := z n ][z 1 := v 1 ] [z n := v n ] Muuttujanvaihdos viimeisessä laskusäännössä on tarpeen, jotta sidotut ja vapaat muuttujat eivät menisi sekaisin (jos esimerkiksi x 2 esiintyy vapaana v 1 :ssä). Näin määritelty monikkoja ymmärtävä let-lauseke on innokkaasti laskeva. Laiskasti laskeva määrittely on toki myös mahdollinen. 4 Tietueet Monikosta on varsin yksinkertainen hyppäys tietueisiin, joissa komponentteihin ei viitata järjestysnumerolla, vaan niille annetaan (staattisesti tiedossa olevat) nimet. Tietueet esiintyvät useimmissa tyypitetyissä kielissä, yleensä tietueen tai struktuurin nimellä ja tietue on myös tyypillisen olioluokan pohjalla. Myös tietueille on mahdollista määritellä purkava let-lause, kuten monikoille tehtiin yllä, mutta tässä valitaan toinen (ja yleisemmin käytössä oleva) ratkaisu: l Labels T, U ::= {l 1 : T 1,..., l n : T n } t, u ::= {l 1 = t 1,..., l n = t n } t.l w ::= {l 1 = v 1,..., l n = v n } Γ t 1 : T 1 Γ t n : T n Γ {l 1 = t 1,..., l n = t n } : {l 1 : T 1,..., l n : T n } Γ t : {l 1 : T 1,..., l k : T k,..., l n : T n } l = l k T = T k Γ t.l : T t k t k {l 1 = t 1,..., l k = t k,..., l n = t n } {l 1 = t 1,..., l k = t k,..., l n = t n } l = l k {l 1 = v 1,..., l k = v k,..., l n = v n }.l v k 4

Tämäkin määrittely laskee innokkaasti laiska määritelmä olisi myös mahdollinen. Tässä määritelmässä tietuetyypit ovat samat, jos niissä esiintyvät sama määrä samannimisiä kenttiä samantyyppisinä samassa järjestyksessä. Määritelmä vastaa C-kielessä käytössä olevaa järjestelyä. Sen hyöty on siinä, että kääntäjä voi staattisesti selvittää pelkän tyypin avulla, kuinka kaukana tietueen alusta haluttu kenttä on. Semanttisesti voisi olla järkevämpää sallia kenttien järjestyksen vaihteleminen, ja toisinaan näin tehdäänkin mutta silloin joudutaan tekemään ajonaikana työtä sen selvittämiseksi, missä kohtaa tietuetta haluttu kenttä on. 5 Variantit Proseduraalisessa ja funktionaalisessa ohjelmoinnissa joissa perintä ei ole käytettävissä on tarpeen kyetä luettelemaan vaihtoehtoisia rakenteita samalle tyypille. C-kielessä tämä toteutetaan käyttämällä unionia (engl. union), Pascalissa varianttitietueita variant records ja Haskellissa algebrallisia tietotyyppejä (engl. algebraic data types). Näille kolmelle yhteinen teoriatausta saadaan varianttityypistä (engl. variant type), joka on muuten samanlainen kuin tietue paitsi että vain yksi kenttä on olemassa kerrallaan. Lisäksi variantin sisällön tarkasteleminen vaatii suorituksen haarautumista sen mukaan, mikä variantin kentistä on kulloinkin käytössä. l Labels T, U ::= l 1 : T 1,..., l n : T n t, u ::= l = t case t of l 1 = x 1 t 1 l n = x n t n w ::= l = v Γ t : T ( k {1,..., n}: l = l k T = T k ) Γ l = t : l 1 : T 1,..., l n : T n Γ, x 1 : T 1 t : T Γ, x n : T n t : T Γ t : l 1 : T 1,..., l n, T m n = m Γ case t of l 1 = x 1 t 1 l n = x n t n : T t t l = t l = t 5

l = l k case l = v of l 1 = x 1 t 1 l n = x n t n t k [x k := v] Näin määritelty varianttityypit sisältävä tyyppijärjestelmä on ensimmäinen kurssilla vastaan tuleva järjestelmä, jossa tyyppisäännöistä ei voi suoraan takaperin lukemalla löytää tyyppitarkastusalgoritmia. Syy on siinä, että varianttilausekkeen l = t tyyppi ei ole yksikäsitteinen. Elegantti ratkaisu ongelmalle on käyttää Hindley Milnerin tyyppipäättelyä. Toinen vaihtoehto on laajentaa kieltä siten, että varianttilausekkeelle tulee aina eksplisiittisesti annettu tyyppi. C-kielen unionityyppi poikkeaa edellä esitetystä siinä, että unionin mitä tahansa kenttää on syntaktisesti mahdollista käyttää milloin vain, eikä tyyppijärjestelmä sen paremmin staattisesti kuin dynaamisestikaan virheellistä käyttöä huomaa. Vastaava ongelma on käytännössä myös Pascalin varianttitietueilla. Haskell-kielen algebrallisissa tyypeissä on kyse varianttityypeistä, joissa kunkin vaihtoehdon tyyppi on automaattisesti joko monikko tai tietue. Tällainen tyyppi määrittelee olennaisesti universaalialgebrasta tutun operaattoriston mikä selittääkin nimen. Luettelotyypit (kuten C:n enum-tyypit, mutta myös kokonaislukutyypit, totuusarvotyyppi jne.) voidaan nähdä varianttityypin erikoistapauksena, jossa kunkin varianttikentän tyyppinä on yksikkötyyppi. 6 Viitetyypit Imperatiivisessa ohjelmoinnissa välttämätön ominaisuus on muuttuja, jonka arvoa voi suoritusaikana muuttaa. Lambdakielessä ja tyyppiteoriassa tämä mallinnetaan erityisenä viitetyyppinä (engl. reference type), jossa muuttujan arvona voi olla viite muistipaikkaan, jonka arvon muuttaminen ajonaikana on mahdollista. Seuraavassa käytetään C++-kielen osoittimista tuttua syntaksia. 6

r Reference T, U ::= T () t, u ::= new t t t u () t; u w ::= r Huomaa: Ensimmäistä kertaa selkäranka (ja siten arvo) ei ole termin erikoistapaus, sillä viittausta edustava r ei ole sallittu termi. Γ t : T Γ new t : T Γ t : T Γ t : T Γ t : T Γ u : T Γ t u : () Γ t : () Γ u : U Γ t; u : U Γ () : () Laskentasäännöissä joudutaan laajentamaan välitilan käsitettä aiemmasta lisäämällä välitiloihin keko (engl. store), joka on osittaisfunktio viittauksista arvoihin. Jokainen aiempi laskentasääntö pitää myös laajentaa kuljettamaan kekoa mukanaan, esimerkiksi: (λx : T t, σ) (λx : T t, σ ) Muut lambda-kielen laskentasäännöt muuttuvat vastaavasti. Uusien konstruktioiden laskentasäännöt ovat seuraavat: r dom σ (new v, σ) (r, σ (r, v)) 7

r dom σ ( r, σ) (σ(r), σ) r dom σ (r v, σ) (r, σ (r, v)) (new t, σ) (new t, σ ) ( t, σ) ( t, σ ) (t u, σ) (t u, σ ) (u, σ) (u, σ ) (t u, σ) (t u, σ ) (t; u, σ) (t ; u, σ ) Jotta tyyppijärjestelmän eheys voitaisiin todistaa etenemis- ja säilymislemmojen avulla, pitää välitiloille ja siten keolle määritellä tyypitys. Sivuutetaan se tässä (Pierce, 2002, 13.4). Viitteet Benjamin C. Pierce. Type and Programming Languages. MIT Press, Cambridge, MA, 2002. 8