6 Algebralliset tietotyypit

Save this PDF as:
 WORD  PNG  TXT  JPG

Koko: px
Aloita esitys sivulta:

Download "6 Algebralliset tietotyypit"

Transkriptio

1 Nyt voitaisiin kirjoittaa instance Functor Set where type Inv Set e = (Ord e) fmap = map jossa metodin tyyppi onkin nyt fmap :: (Ord a,ord b) => (a -> b) -> Set a -> Set b joka onkin nyt samaa tyyppiä kuin kirjastofunktio Data.Set.map. Nykyinen laajennus tulee käyttöön määrittelyillä {-# LANGUAGE ConstraintKinds,... #-}... import GHC.Exts(Constraint) joilla otetaan käyttöön 1 ensimmäiseksi kielilaajennus 2 toiseksi uusi laji. 6 Algebralliset tietotyypit Haskellin datan kaltaisia tietotyyppeja, joiden arvoja kootaan konstruktoreilla tutkitaan hahmonsovituksella kutsutaan algebrallisiksi tietotyypeiksi (Algebraic Data Type, ADT). Tämän nimityksen takana on idea, että sellaisen tyypin τ arvojen joukko A τ on matemaattisesti yksi englanniksi: finitely generated free algebra suomennos: äärellisesti tuotettu vapaa algebra. Matematiikassa yksi algebra tarkoittaa sellaista rakennetta, jossa on joukko ja laskutoimituksia sen alkioilla, eli funktioita joiden parametrit ja tulos kuuluvat tähän joukkoon. Esimerkiksi sanomme että luonnolliset luvut N sekä niiden yhteenlasku + ja kertolasku muodostavat sellaisen algebran, jossa pätee.... Yleisinimi algebra tarkoittaa sitä matematiikan haraa, joka tutkii tällaisia rakenteita ja mitä niissä pätee. ADT-ideassa joukkona on A τ ja sen laskutoimituksina ovat tyypin τ konstruktorit, koska ne 99

2 saavat parametreinaan toisia joukon A τ alkioita (kun tarkastellaan vain niitä parametreja, joiden tyyppi on sama τ) tuottavat niistä arvonaan joukon A τ uuden alkion. Joukko voidaan tuottaa äärellisesti jos on olemassa äärellinen kokoelma funktioita, joita käyttämällä saadaan kaikki sen alkiot. Vakiot ovat parametrittomia funktioita. Esimerkiksi luonnolliset luvut N voidaan tuottaa äärellisesti vakiosta Z eli nolla funktiolla S(n) eli lukua n seuraava luku. eli 0 = Z, 1 = S(Z), 2 = S(S(Z)), 3 = S(S(S(Z))),... Siis äärettömänkin joukon voi tuottaa äärellisesti. ADT-ideassa data-määritelmä on tämä äärellinen kokoelma konstruktoreita. Ahkerassa kielessä olisi A τ = A pienin τ jonka voi tuottaa äärellisesti tähän tapaan. Haskellin laiskuuden vuoksi sen joukkona onkin A suurin τ jota ei voikaan tarkkaan ottaen tuottaa äärellisesti tähän tapaan koska siellä ovat myös äärettömät alkiot. Tarkkaan ottaen Haskellissa pitäisikin siis puhua koalgebroista ja sellaisista tietotyypeistä. Algebra on vapaa jos sen joukon alkioiden välillä on vain pakolliset yhtälöt, mutta ei mitään muita yhtälöitä. Jos f on n-parametrinen funktio algebrassa, niin jos a 1 = b 1 ja a 2 = b 2 ja a 3 = b 3 ja... ja a n = b n niin myös f a 1 a 2 a 3... a n = f b 1 b 2 b 3... b n (12) on tällainen pakollinen yhtälö muutenhan f ei olisikaan funktio. Vapaassa algebrassa on vain nämä yhtälöt (12). Silloin tällainen implikaatio (12) vahventuu ekvivalenssiksi jos ja vain jos. Esimerkiksi luonnollisten lukujen N ja niiden yhteenlaskun + muodostama algebra ei ole vapaa, koska siellä on myös muitakin yhtälöitä kuten vaihdannaisuus a + b = b + a. Vapaita algebroja käytetään teoreettisen tietojenkäsittelyn monilla eri osa-alueilla, koska ne ovat puhtaan syntaktisia ilman muiden yhtälöiden lisäämää semantiikkaa. ADT-ideassa algebra ajatellaan vapaa: Kun yhtälössä (12) funktio f onkin konstruktori, niin se sanoo että jos kentät ovat yhtäsuuret niin myös konstruoidut arvot ovat yhtäsuuret. Viittausten läpikuultavuus takaa sen Haskellissa. 100

3 Ilman viittausten läpikuultavuutta pitää erotella yhtäsuuruus vs. samuus esimerkiksi Javan equals vs. ==. Implikaatio (12) vahventuu ekvivalenssiksi, koska jos jonkin kentän arvot a i b i niin ohjelmoija yllättyisi jos konstruoidut arvot olisivatkin silti yhtäsuuret. (Sillon yhtäsuuruus ei ottaisikaan huomioon kaikkia kenttiä. Haskell-ohjelmoija voi määritellä tällaisen Eq-jäsenyyden käsin, mutta se on varsin epätavallista.) Tästä algebrallisesta näkökulmasta hahmonsovitus on yhtälön case lauseke of Hahmo -> haara ratkaisemista tässä vapaassa algebrassa. Se on selvästi täyttä yhtälönratkaisua helpompaa: lauseke = Hahmo (13) Vain Hahmossa esiintyy muuttujia joille pitää löytää arvot, lauseke on muuttujaton. Siksi tätä kutsutaankin sovitukseksi. Algebran vapauden vuoksi ainoa ratkaisukriteeri on syntaktinen samuus: Yhtälö (13) pätee jos ja vain jos kumpikin puoli alkaa samalla konstruktorilla ja niiden kentätkin sovittuvat pareittain toisiinsa. Kukin näistä muuttujista esiintyy Hahmossa vain kerran, joten muuttujan arvoksi ei koskaan ole kahta kilpailevaa vaihtoehtoa. lauseketta sievennetään kohti arvoaan vain sen verran kuin tämän yhtälön (13) ratkaisu vaatii. 6.1 Haamutyypit datan tyyppiparametria kutsutaan haamutyypiksi (phantom type) jos sitä ei tarvitakaan määriteltävän tyypin arvoissa. Tavallisin haamutyyppi esiintyy datassa yhtäsuuruusmerkin = vasemmalla puolella mutta ei sen oikealla puolella. Myös kuvan 3 Braun-puun tyyppiparametri t on haamutyyppi, koska sen arvojen rakenne ei riipu siitä, mikä tyyppi t on: Täsmälleen samat arvot olisi saatu määrittelyllä data Braun u = Braun { value :: u, zero :: Braun u, one :: Braun u } ilman tätä haamutyyppiparametria t. Tämä haamutyyppiparametri t muistaa sen Integral- eli kokonaislukutyypin, jolla growbraun puun loi jotta lookbraun osaa palauttaa myöhemmin samantyyppisen (eikä pelkästään -sisältöisen) funktion. 101

4 Määrittely Braun unohtaisi tämän tyypin, jolloin olisi mahdollista vaikkapa 1 ensin luoda growbraunilla puu tyyppiä Braun Bool funktiolle joka on tyyppiä Integral -> Bool 2 sitten lukea lookbraunilla siitä funktio, jonka tyyppi onkin Int -> Bool koska itse puussa ei ole mitään informaatiota siitä, oliko tyyppi luotaessa Integer vai Int (vai Word vai...). Näin haamutyyppiparametrilla voi esittää sellaista tyyppi-informaatiota, jota ei voi päätellä tyypin arvoista, ja joka siis kertoo jotakin muuta ja abstraktimpaa kuin kyseinen tietorakenne. ghc sallii jopa tyhjät data-määrittelyt. Niissä on vain yhtäsuuruusmerkin = vasen puoli, mutta ei lainkaan oikeata puolta. Koska tällaisessa määritelmässä ei ole lainkaan konstruktoreita, ei näin määritellyillä tyypeillä ole yhtään arvoa (paitsi ). Tällainen tyyppi tai tyyppikonstruktori onkin tarkoitettu käytettäväksi vain haamutyyppiparametrin arvona. 6.2 Eksistentiaaliset tyypit Haamutyyppiparametri on sellainen tyyppiparametri, joka esiintyy data-määritelmässä yhtäsuuruusmerkin = vasemmalla puolella, vaikka sitä ei tarvitakaan sen oikealla puolella. Sillä voi lisätä tyyppiin sellaista informaatiota, joka ei käy ilmi tyypin arvoista. Vastaavasti ghc-kielilaajennus ExistentialQuantification sallii uuden tyyppiparametrin käyttämisen vain sen oikealla puolella, kunhan se forall-esitellään sitä käyttävän konstruktorin alussa. Vastaavasti sillä voi poistaa tyypistä informaatiota, ja luoda arvoihin kenttiä joiden tyyppi on tuntematon, mutta se voi yhä olla tässä ja nyt -monimuotoinen. Siten data T a = forall b. (R b) => K a b... määrittelee tyypille T sellaisen konstruktorin K jonka tyyppi on K :: forall b. (R b) => a -> b -> T a jonka jälkimmäisen kentän tyyppi b on jokin tyyppiluokan R jäsenistä mutta tulostyyppi T a ei ilmaisekaan mikä niistä. Kun tämän konstruktorin K tuottama arvo sopii hahmoon K x y niin sen jälkimmäisen kentän sisältö y on tätä tuntematonta tyyppiä b, josta tiedetään vain sen rajoite R b. 102

5 Haskellin tyyppiturvallisuuden vuoksi tätä sisältöä y voi käsitellä vain sen rajoitteen R lupaamilla metodeilla koska sen todellisesta tyypistä b ei tiedetä enää mitään muuta. Esimerkiksi Javassa List<? extends R> ilmaisee tyypin lista, jonka alkiot kuuluvat olioluokan R aliluokkiin. Sen alkiot muistavat yhä sisäisesti oman aliluokkansa, joten tässä ja nyt -monimuotoisuus valitsee jokaiselle alkiolle sen oman toteutuksen luokan R metodeille. Vastaavasti apumääritelmän data A = forall a. (R a) => E a avulla Haskell-listatyyppi [A] koostuu alkioista muotoa E y jossa sisällön y tyyppi kuuluu tyyppiluokkaan R. Sen alkiot muistavat yhä sisäisesti oman tyyppinsä, joten tässä ja nyt -monimuotoisuus valitsee jokaiselle alkiolle sen oman toteutuksen tyyppiluokan R metodeille. Siten esimerkiksi data H = forall a. (Show a) => S a luo sellaisen tyypin, jossa: Arvot ovat ( H tai) muotoa S y jossa y on mikä tahansa sellainen arvo jolle on määritelty metodi show Kentän arvoon y voi soveltaa vain tätä metodia show. Tämä soveltaminen show y tulostaa arvon y merkkijonoksi niin kuin sen sen tyyppiset arvot tulostetaan vaikka kutsuja ei tiedäkään, mikä sen tyyppi on. Siten esimerkiksi [S 123, S "hei", S True] :: [H] koska jokainen alkio on samaa tyyppiä H vaikka jokaisessa niistä kenttä onkin eri tyyppiä. Tähän listaan voi soveltaa funktiota map (\ (S y) -> show y) koska jokainen kentän arvo y on jotakin tyyppiluokkaan Show kuuluvaa tyyppiä. Tuloksena on ["123","\"hei\"","True"] jossa jokainen kentän arvo y on tulostunut oman tyyppinsä mukaisella tavalla. Tällaista tyyppiä kutsutaan eksistentiaaliseksi (existential) koska sen sisällöllä on jokin tyyppi, vaikka vain sisältö itse tietää mitä tyyppiä se on. Eksistentiaalinen tyyppi piilottaa rajapinnan toteutuksen (piilottamalla sen toteuttavan tarkan tyypin) ja on siten väline abstraktin (abstract) tietotyypin luomiseen. 103

6 6.3 Yleistetyt algebralliset tietotyypit Haamutyyppiparametrit ja eksistentiaaliset tyypit ovat erikoistapauksia yleistetyistä algebrallisista tietotyypeistä (generalized ADT, GADT). Tavallinen uuden tyypin määrittely kuten data Nimi a = Konstruktori Kenttä_1 Kenttä_2... luo konstruktorin, jonka tyyppi on Konstruktori :: Kenttä_1 -> Kenttä_2 -> Nimi a jonka parametreina ovat kentät ja tuloksen tyyppi on täsmälleen sama kuin määriteltävänä oleva tyyppi. ghc-laajennuksella GADTs saa niiden lisäksi käyttöön myös määrittelytavan data Nimi a where Konstruktori :: Kenttä_1 -> Kenttä_2 -> Nimi a... jossa ohjelmoija kirjoittaakin itse konstruktoreidensa tyypit. (Haskell luo konstruktorit kuten ennenkin.) Näin ohjelmoija pääsee tyypittämään konstruktorinsa kuten hän itse haluaa käyttäen kaikkea mitä Haskell tarjoaa. Jos ohjelmoija haluaa että Kenttä_1 on eksistentiaalinen, niin hän voi tyypittää sen Konstruktori :: (forall b. Kenttä_1) -> Kenttä_2 -> Nimi a ottamalla käyttöön toisen ghc-laajennuksen Rank2Types joka sallii forallin funktion parametrin sisällä. (Tai RankNTypes joka sallii myös sisäkkäiset forallit.) Ohjelmoija voi tyypittää tarkemmin myös konstruktorinsa tuloksen: Sen ei tarvitsekaan olla täsmälleen sama Nimi a kuin datan perässä, vaan ohjelmoija voikin antaa sen tyyppiparametrille a haluamansa arvon. Siis yhdellä konstruktoreista voisi olla tulostyyppinään Nimi Int, toisella taas Nimi Bool, jne. Erityisesti jokainen konstruktori voi antaa näin haluamansa arvon haamutyyppiparametrille a jota ei käytetty kenttien tyypeissä. 7 Monadit Puhtaassa ohjelmointikielessä funktioilla ei saa olla sivuvaikutuksia. Toisaalta vaikkapa I/O-operaatioilla on sivuvaikutuksia: esimerkiksi operaatio putstr eli tulosta merkkijono stdoutiin tehdään juuri sivuvaikutuksensa eli tulostamisen vuoksi ei siksi että kutsuja olisi kovin kiinnostunut sen palauttamasta tuloksesta. 104

7 Laiskassa ohjelmointikielessä myös näiden sivuvaikutusten tahdistaminen on pulmallista: Jos jotakin lasketaan vain silloin (tai jos!) sen tulosta tarvitaan, niin milloin tehdään putstr jonka tulos ei kiinnosta kutsujaa? Haskell on omaksunut monadit (monad) vastaukseksi muun muassa tällaisiin ongelmiin. Monadin yleinen idea syntyi kategoriateoriassa (category theory) joka on eräs matematiikan osa-alue. Tämä osa-alue on muutenkin hedelmällinen (funktionaalisen) ohjelmoinnin teorian kannalta. Monadeihin voi tutustua tästä alkuperäisestä matemaattisesta näkökulmasta, mutta me otamme niihin sen sijaan (Haskell-)ohjelmoinnin näkökulman. Valitettavasti sama termi monadi on käytössä myös algebrassa, joka on matematiikan eri osa-alue ja termi kategoria on käytössä myös muualla, kuten formaalissa kielitieteessä. Tällä monadin yleisellä idealla on paljon käyttökohteita Haskellissa. Siksi Haskellin kirjastoissa on paljon yksittäisiä monadeja eri tarkoituksiin. Haskell-ohjelmoinnin näkökulmasta monadi m :: * -> * on 1-parametrinen tyyppikonstruktori, jonka intuitio on: m a on sellaisten laskentojen (computation) tyyppi, että jos sellainen laskenta suoritetaan, niin se tuottaa lopuksi vastauksen tyyppiä a. Näin monadi m erottaa toisistaan laskennan muodostamisen jonka voi nyt ohjelmoida tavallisena operaationa, joka käsittelee sellaisia arvoja, joiden tyyppi on m jotain. Esimerkiksi peräkkäissuoritus 1 tee ensin tämä 2 ja sen jälkeen tuo ilmaistaan 1 muodosta yksi laskenta= ensin tämä ja sen jälkeen tuo kahdesta pienemmästä laskennasta tämä ja tuo kuten (++) 2 suorita näin muodostettu laskenta. suorittamisen joka on jakamaton operaatio, eli kun jotakin laskentaa ryhdytään suorittamaan, niin se suoritetaan loppuun saakka, jotta saadaan tietää sen vastaus. Tällainen jakamaton suoritus voi tehdä sellaisia sivuvaikutuksia, jotka eivät näy sen ulkopuolelle. Monadissa m sallittu operaatio on siten tavallinen Haskell-funktio, jonka tyyppi on operaatio :: parametri(t) -> m vastaus 105

8 eli se tekee parametristaan laskennan, jonka suorittamisesta tulee sen vastaus. Myös sen parametrilla voi olla tyyppi m jokin. Silloin se on tämän monadin m kontrollirakenne. Esimerkiksi peräkkäissuoritus on määritely operaattorina (>>) :: (Monad m) => m a -> m b -> m b Tämän vuoksi monadeja kutsutaan joskus ohjelmoitavaiksi puolipisteiksi intuitiivisesti koska ohjelmoija voi määritellä mitä tämä;tuo tarkoittaa määrittelemällä mitä (>>) hänen omassa monadissaan tarkoittaa. Monadin M laskenta suoritetaan puolestaan funktiolla tyyppiä runm :: parametri(t) -> M vastaus -> vastaus. Vaikka monadit ovatkin ohjelmointikieliriippumaton idea, niin Haskell soveltuu niille erityisen hyvin: Monadit ovat viivästettyä laskentaa, joka ensin määritellään ja myöhemmin suoritetaan. Laiskassa suorituksessa tämä on automaattista ja siten vaivatonta, kun taas ahkerassa suorituksessa ohjelmoija joutuisi kirjoittamaan viivästyksen käsin. Laiskassa suorituksessa laskennan esittäminen monadisena tietorakenteena jota suoritetaan askel askeleelta on yhtä luontevaa kuin laiskan listan sieventäminen kohti arvoaan alkio alkiolta silloinkin kun tulos on päättymätön. Ahkerassa suorituksessa tietorakenteet ovat äärellisiä. Yleiskäsite monadit voidaan esittää luontevasti tyyppiluokkana. Tämä konstruktoriluokka on class Monad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a Tässä ovat ne 2 metodia, jotka jokainen sen jäsen määrittelee omalla tavallaan. return x tekee tyyppinsä perusteella parametristaan x sellaisen laskennan, joka palauttaa tämän saman arvon x. returnin idea on luoda yksinkertaisin mahdollinen laskenta, joka ei tee mitään muuta. Haskellin return ei ole kontrollirakenne vaan tavallinen metodi. Se ei siis pomppaa ulos nykyisestä laskennasta. Tämä nimi on valittu siksi, että return on yleensä se funktio, jota laskenta kutsuu viimeiseksi palauttaakseen vastauksensa kutsujalleen. Operaattori (>>=) on se yleisperiaate jolla kaksi laskentaa tämä ja tuo yhdistetään peräkkäin yhdeksi laskennaksi ensin tämä ja sitten tuo. Idea näkyy sen jälkimmäisen argumentin tyypistä a -> m b. 106

9 Parametrityyppinsä a perusteella se saa parametrinaan sen arvon x :: a jonka tämä :: m a laskenta tuottaa. Siten yhdistyn laskennan pitää alkaa sillä, että ensin tehdään tämä jotta saadaan x. Tulostyyppinsä m b perusteella se tuottaa tuon laskennan, johon yhdistetty laskenta päättyy. Saatu x voi vaikuttaa siihen, millainen laskenta tuosta tulee. Yhteenvetona siis p >>= q sanoo suorita ensimmäinen laskenta p jotta tiedät millaisella laskennalla q x sen jälkeen pitää jatkaa. Aikaisemmin mainittu peräkkäissuoritusoperaattori p >> q = p >>= \_ -> q on se erikoistapaus, jossa tämän laskennan tulos x ei vaikutakaan tuohon laskentaan silti tämä suoritetaan vaikka sen tulosta x eri käytetäkään, jotta saadaan tuo. Näin monadi on onnistunut esittämään peräkkäisyyden ensin tämä ja sitten tuo Haskellin laskentamallissa, joka ei perustu kontrollivuon ohjailuun vaan tietoriippuvuuksiin: Koska kutsusta run_m koko halutaan vastaus niin koko laskennan viimeinen askel pitää suorittaa, mutta sitä ennen pitääkin suorittaa sen toiseksi viimeinen askel, mutta sitä ennen... Siten Haskellin laskentamalliin voi liittää kontrollivuon ohjailuun perustuvaa laskentaa kunhan se tehdään sille sopivassa monadissa. Monet monadeista onkin määritelty newtypellä jolloin näitä käännösaikaisia tietoriippuvuuksia ja -tyyppejä ei olekaan enää suoritusaikana. Sellainen monadi käyttää Haskellin tyyppijärjestelmää määrittelemään halutun ohjelmointikurin jota ohjelmoija tulee automaattisesti noudattaneeksi kirjoittaessaan siinä monadissa toimivaa koodia. Tyyppikonstruktorin m täytyy kuitenkin toteuttaa monadilait ollakseen järkevä monadina. Lakien perusidea on, että operaation(>>=) pitää olla liitännäinen ja returnin pitää olla sen neutraalialkio kuten (++) ja []. Lakien yksi muotoilu on return x >>= f f x (14) f >>= return f (15) (f >>= g) >>= h f >>= (\ x -> g x >>= h). (16) Liitännäisyyslain (16) idea on, että kaikki peräkkäiset laskennat kuten ensin tämä, sitten tuo, ja lopuksi se (ensin tämä, sitten tuo) ja lopuksi se ensin tämä, sitten (tuo, ja lopuksi se) ovat samat riippumatta siitä, miten ne on suluin ryhmitelty. 107

10 Vasemmanpuoleisen neutraalialkiolain (14) ja oikeanpuoleisen neutraalialkiolain (15) idea on, ettei return tee muuta laskentaa kuin välittää parametrinsa eteenpäin. Monadit ovat keskeisiä nykyisessä Haskell-standardissa. Erityisesti I/O-operaatiot suoritetaan omassa IO-monadissaan. Tutkimuksessa on kehitetty monadeja eteenpäin esimerkiksi nuoliksi (arrow). Monadinen tyypitys ja ohjelmointityyli on monoliittista. Jos funktio f haluaa kutsua jonkin monadin M operaatiota, jonka tyyppi on siis jokin g ::... -> M tulos niin silloin myös sen oma tyyppi on f ::... -> M vastaus. Olkoon M vaikkapa jokin sellainen monadi, joka sallii tietyt sivuvaikutukset (kuten I/O-operaatiot). Koska f haluaa kutsua operaatiota g, jolla voi siis olla näitä sivuvaikutuksia, niin myös funktiolla f voi olla näitä samoja sivuvaikutuksia. Siten ohjelmoijan on jo suunnitteluvaiheessa päätettävä tuleeko koodista monadista vai tavallista tavallisen koodin monadisointi jälkikäteen pakottaa kirjoittamaan sen uudelleen. 7.1 Monadinen syntaksi Monadin M laskentoja voi ketjuttaa peräkkäin tällä operaattorilla(>>=), ja tällaisen ketjun lopussa on tavallisesti return vastaus. Haskell sisältää erityisen do-syntaksin helpottamaan tällaista laskentojen ketjuttamista. do-syntaksi tekee koodista imperatiivisemman näköistä, mutta kyse on silti funktionaalisesta koodista. do-syntaksi muistuttaa listojen erikoissyntaksia koska itse asiassa listatkin ovat eräs monadi. Toisto ilmaistaan näissä laskennoissa Haskellin tavalliseen tapaan rekursiolla. Monadin M do-lausekkeen syntaksi on do{ lause ; lause ; lause ;... ; lauseke } jossa lause on 108

11 Hahmo <- lauseke jossa lauseke :: M a ja Hahmo :: a joka tarkoittaa suorita se laskenta jonka tämä lauseke antaa ja nimeä sen vastaus tällä Hahmolla lauseke :: M a on Haskell-lauseke jonka vastaus lasketaan. Jos se on don viimeisenä niin se antaa koko don vastauksen ja sen tyypin ja se onkin useimmiten return vastaus sisällä niin sen vastausta ei nimetäkään millään Hahmolla eli se suoritetaankin vain sivuvaikutustensa vuoksi let määritelmät (ilman in-osaa) tekee paikalliset määritelmät, jotka näkyvät tämän don loppuun saakka. Aaltosulut {...} ja niiden sisällä olevat puolipisteet ; voi jättää pois do-lausekkeesta sisentämällä sen sisältö keskenään samaan sarakkeeseen. do-lauseke kääntyy tavalliseksi Haskell-lausekkeeksi kirjoitusjärjestyksessä seuraavasti: Jos ensimmäinen lause on do{ Hahmo <- lauseke ; loput } niin sen käännös on jonka let ok Hahmo = do{ loput } ok _ = fail virheilmoitus in lauseke >>= ok ok on uusi apufunktio fail :: String -> M a on tämän monadin M metodi, jonka oletustoteutus päättää laskennan sopivaan virheilmoitukseen ja vastaukseen M a Hahmonsovituksen on tarkoitus onnistua, joten vain harvat monadit määrittelevät failiaan uudelleen. Jos ensimmäinen lause on yksinkertaisempi do{ lauseke ; loput } niin sen käännöskin on yksinkertaisempi lauseke >> do{ loput } Jos ensimmäinen lause on do{ let määritelmät ; loput } niin sen käännös on 109

12 let määritelmät in do{ loput } Koko don viimeinen do{ lauseke } on se lauseke itse. Otetaan esimerkkinä 1 summa = 0; 2 repeat 3 tulosta nykyinen summa; 4 seuraava = lue seuraava rivi numerona; 5 summa = summa + seuraava 6 until seuraava = 0; 7 return summa. summaa1 operaattorilla (>>=) summaa2 do-syntaksilla. Käytämme niissä I/O-monadin operaatioita riviä 3 ja putstr :: String -> IO () readln :: (Read a) => IO a riviä 4 varten. summaa1,summaa2 :: IO Double summaa1 = let silmukka summa = putstr (show summa ++ " > ") >> readln >>= \ seuraava -> if seuraava == 0 then return summa else silmukka (summa+seuraava) in silmukka 0 summaa2 = let silmukka summa = do putstr (show summa ++ " > ") seuraava <- readln if seuraava == 0 then return summa else silmukka (summa+seuraava) in silmukka 0 110

13 ulkomaailma syöte tulostus IO-monadi kutsuu funktionaalinen koodi Haskell-sovellus 7.2 IO-monadi Kuva 4: Haskell-sovelluksen yleisrakenne. Haskellin I/O-operaatiot ovat monadissa IO. IO on siinä(kin) mielessä erityinen monadi, että sillä ei ole omaa suoritusfunktiota tyyppiä runio :: IO a -> a koska sellaisen pitäisi pystyä kapseloimaan parametrinaan saamansa I/O-laskennan sivuvaikutukset niin, etteivät ne näkyisi tämän funktion ulkopuolelle. Se taas olisi mahdotonta, koska esimerkiksi kun getchar :: IO Char lukee seuraavan merkin oletussyötevirrasta stdin, niin tämä merkki katoaa sieltä eivätkä muut runio-kutsut sitä enää näkisi. Siksi Haskell-ohjelma käynnistyy valmiiksi IO-monadissa: Tulkin ghci komentorivillä voi suorittaa IO-lausekkeita. Käännetyn Haskell-ohjelman pääohjelma on main :: IO () josta ohjelman suoritus alkaa. Siten IO-koodi voi kutsua funktionaalista koodia, mutta funktionaalinen koodi ei voi kutsua IO-koodia. Tämä vuoksi Haskell-sovelluksen yleisrakenne on Kuva 4 mukainen, eli IO-monadi kommunikoi ulkomaailman kanssa ja kutsuu ohjelman funktionaalista koodia niiden välisenä suojakerroksena. Preluden perusfunktioita tekstimuotoiseen tulostukseen oletustulosvirtaan stdout ovat putchar :: Char -> IO () joka tulostaa yhden merkin putstr :: String -> IO () joka tulostaa merkkijonon putstrln :: String -> IO () joka tulostaa merkkijonon ja rivinvaihdon print :: (Show a) =>a -> IO () joka on putstrln. show ja jota tulkki ghci kutsuu laskemalleen arvolle silloin kun sen tyyppi kuuluu tähän tyyppiluokkaan. syötteen lukemiseen oletussyötevirrasta stdin ovat 111

14 getchar :: IO Char joka lukee yhden merkin getline :: IO String joka lukee yhden rivin. Jos syötteen tiedetään esittävän tyyppiä a olevaa arvoa, niin silloin tämä arvo saadaan seuraavilla funktioilla: readio :: (Read a) =>String -> IO a joka konvertoi annetun merkkijonon tyypin a arvoksi readln :: (Read a) =>IO a joka lukee syöterivin oletussyötevirrasta stdin ja konvertoi sen. Jos merkkijonoa konvertoitaessa törmätäänkin syntaksivirheeseen, niin siitä seuraa I/O-poikkeus, jonka ohjelmoija voi käsitellä kuten jatkossa kuvataan. Funktionaalisempaa syötteen käsittelyä on funktio getcontents :: IO String joka palauttaa oletussyötevirran stdin koko (jäljellä olevan) sisällön laiskana merkkijonona, jota luetaan sitä mukaa kun ohjelma etenee sen merkistä seuraavaan. Se on deklaratiivinen (joskin hieman hidas) tapa lukea syöte eräajo-ohjelmaan jonka jälkeen siihen voi soveltaa kaikkia Haskellin tarjoamia listankäsittelyfunktioita. Funktionaalisempaa oletussyötevirran stdin ja oletustulosvirran stdout käsittelyä on funktiointeract :: (String -> String) -> IO () jonka parametri onkin puhdas Haskell-funktio joka saa syötteenään oletussyötevirran stdin koko (jäljellä olevan) sisällön laiskasti luettavana merkkijonona antaa tuloksenaan oletustulosvirtaan stdout laiskasti kirjoitettavan merkkijonon. Nimestään huolimatta sekin on tarkoitettu lähinnä eräajo-ohjelmiin. Mutkikkaammat I/O-operaatiot kuten esimerkiksi tiedostojen käsittely löytyvät vakiokirjastosta System.IO. Esimerkiksi usein halutaan oletustulosvirta stdout sellaiseksi, ettei sitä puskuroidakaan, vaan tulostus tapahtuukin välittömästi. Siihen System.IO tarjoaa kutsun hsetbuffering stdout NoBuffering. Puskuroinnin asetukset aiheuttavat harmeja eri käyttöjärjestelmien ja -ympäristöjen välillä. Esimerkiksi getchar lukee seuraavan merkin Windowsissa vasta kun sen sen sisältämä rivi on lähetetty ohjelmalle Enter - näppäimellä Linuxissa tavallisesti heti kun käyttäjä painaa näppäintä, mutta tämä riippuu terminaaliasetuksista. Poikkeukset (exception) ovat erittäin hyödyllisiä. Erityisesti I/O-operaatioissa voi tapahtua ohjelmasta riippumattomia virheitä, joiden käsittely erikseen jokaisen I/O-operaation jälkeen olisi vaivalloista. 112

15 Poikkeusten käsittely on kuitenkin hankala sovittaa yhteen puhtaan funktionaalisen ohjelmoinnin kanssa: Se milloin poikkeus käsitellään olettaa, että ohjelmoija tietäisi milloin jotakin tapahtuu laskennan kuluessa mutta puhtaassa funktionaalisessa ohjelmoinnissahan ohjelmoija tietää korkeintaan että se joskus tapahtuu... Haskellin vakiokirjasto System.IO.Error tarjoaakin yksinkertaisen poikkeusmekanismin erilaisten I/O-virheiden käsittelyyn koska monadissa IO on tällainen järjestys, jonka määrää (>>=). Toteutuksen ghc mukana tulee myös sen omakin kirjasto Control.Exception jolla poikkeuksia voi nostaa myös puhtaassa Haskell-koodissa käsitellä silti vain monadissa IO. Vakiokirjaston I/O-poikkeusmekanismi koostuu tyypistä IOError eli jokin I/Ovirhe sekä funktioista (jotka eivät siis ole uusia kontrollirakenteita) ioerror :: IOError -> IO a joka nostaa parametrina ilmoitetun I/O-poikkeuksen catch :: IO a -> (IOError -> IO a) -> IO a jonka ensimmäinen parametri on I/O-tyyppinen lauseke (kuten esimerkiksi jokin do-lauseke) jonka laskenta voi aiheuttaa I/O-poikkeuken. Laskenta ei tavallisesti aiheuta I/O-poikkeusta, ja silloin catchin arvoksi tulee laskennan antama arvo. jälkimmäinen parametri on funktio, jota kutsutaan, jos laskenta aiheuttaakin I/O-poikkeuksen. Se saa parametrinaan sen aiheutuneen poikkeuksen. Se voi käsitellä kyseisen poikkeustilanteen palauttamalla jonkin arvon, josta tulee tämän catchin arvo. Jos se ei osaakaan käsitellä tilannetta, niin sen pitääkin nostaa sama poikkeus uudelleen, jolloin tilanteen käsittelyvastuu siirtyykin seuraavalle ulommalle catchille. Jos mikään catch ei osaakaan sitä käsitellä, niin silloin koko laskenta keskeytyy suoritusaikaiseen virheeseen a. try :: IO a -> IO (Either IOError a) joka koettaa suorittaa parametrinaan saamansa laskennan. Jos sen arvo on Right x niin tämä laskenta eteni virheittä ja antoi tämän lopputuloksen x Left e niin silloin se aiheuttikin poikkeuksen e. Siten try tekee myös poikkeuksesta e tavallisen arvon. Toteutuksen ghc omassa vakiokirjastossa sen nimi onkin tryioerror. Otetaan sitten esimerkiksi I/O-ohjelmoinnista nelilaskin, jossa pidetään muistissa yhtä liukulukua kerrallaan käyttäjä voi antaa komentonaan lisää/vähennä/kerro/jaa se luvulla... tämän komentorivin mahdolliset virheet käsitellään tyhjä komentorivi lopettaa ohjelman suorituksen. 113

16 import System.IO import System.IO.Error main :: IO () main = laskin 0 laskin :: Double -> IO () laskin muisti = do putstr $ "Muistissani on: " ++ show muisti ++ "\nkomentosi? " komentorivi <- getline case komentorivi of "" -> do putstrln "Kiitos!" return () (komento:rivi) -> case lookup komento komennot of Nothing -> do putstrln $ "Tunnen vain seuraavat laskutoimitukset: " ++ map fst komennot ++ "!" laskin muisti Just operaattori -> tryioerror (readio rivi) >>= either (const $ do putstrln "Tajuan vain liukulukuja!" laskin muisti) (laskin. (muisti operaattori )) komennot :: [(Char,Double->Double->Double)] komennot = [( +,(+)),( -,(-)),( *,(*)),( /,(/)) ] Monadissa IO voi käyttää uudelleensijoitettavia muistipaikkoja ghc-kirjastosta Data.IORef taulukoita ghc-kirjastosta Data.Array.IO jos käyttöliittymään tarvitaan proseduraalista ohjelmointia. Haskellin keskeinen käytännön puute on, ettei sille ole standardoitua kirjastoa graafisten käyttöliittymien tekemiseen, eikä tahoa joka sellaista ylläpitäisi. Haskellille on tehty akateemisesti tai harrastepohjalta 114

17 matalan tason kirjastoja kuten ghc:n Windows- ja Haskell Platformin OpenGLrajapinnat. välitason kirjastoja kuten Gtk2HS jolla voi käyttää ilmaista käyttöliittymänsuunnittelutyökalua Glade. Käyttöliittymän toiminnallisuus ohjelmoidaan monadissa IO. korkean abstraktiotason kirjastoja kuten Gtk2HS:n päälle rakennettu Grapefruit, jossa käyttöliittymän toiminnallisuus ohjelmoidaankin monadin IO sijaan nuolilla. 7.3 Tuttuja tyyppejä monadeina Monet tutut tyyppikonstruktorit voi nähdä monadeina. Esimerkiksi Mayben voi nähdä sellaisten laskentojen tyyppinä, jotka voivat myös päättyä saamatta aikaan mitään vastausta. Tämän näkökannan ilmaisee instance Monad Maybe where (Just x) >>= k = k x Nothing >>= k = Nothing return = Just fail s = Nothing sanomalla, että jos peräkkäissuorituksessa (>>=) edeltävästä askeleesta tuli vastaukseksi Nothing niin myös tämänkin askeleen vastaus on Nothing. Se on esimerkki Monadista, jonka fail onkin osa laskentaa. Silloin esimerkiksi Maybe a -tyyppisessä do-lausekkeessa Hahmo <- lauseke toimii siten, että jos lauseke :: Maybe b antaa vastauksen Just x niin Hahmoa sovitetaan tähän x. Jos se sopii niin do-lausekkeen suoritus jatkuu normaalisti näillä Hahmon uusilla nimennöillä ei sovikaan niin suoritetaankin fail "...". Nothing niin koko do-lausekkeen vastaus onkin Nothing. Tämä tapahtuu siis niin, että jokainen keskeneräinen (>>=) saa vastauksekseen Nothing eikä se siis suoritakaan jälkimmäistä parametriaan k. fail "...":: Maybe b suoritetaan kuten Nothing yllä. Esimerkkinä olkoon tilanne, jossa pitää tarkistaa onko kummassakin Mapissa p ja q määritelty arvo avaimelle x. Jos on, niin palautetaan Just niiden arvojen muodostama pari. Jos ei ole, niin palautetaan Nothing. Tämän voi ilmaista do-syntaksilla paljon selvemmin kuin ilman sitä. 115

18 import qualified Data.Map as Map molemmissa x p q = maybe Nothing (\ xp -> maybe Nothing (\ xq -> Just (xp,xq)) (Map.lookup x q)) (Map.lookup x p) kummassakin x p q = do xp <- Map.lookup x p xq <- Map.lookup x q return (xp,xq) Näin Maybe tarjoaa siis yksinkertaisen poikkeusmekanismin sellaiselle puhtaan funktionaaliselle koodille joka on kirjoitettu monadisella ohjelmointityylillä (eli käyttäen do-notaatiota tai (>>=)-operaattoria) jossa tällaista poikkeusta ei käsitellä vaan se päättää laskennan Nothingiin jonka poikkeuksissa ei välitetä mitään lisäinformaatiota esimerkiksi failin merkkijonoparametri unohdetaan. Monipuolisemman poikkeusmekanismin puhtaalla monadisella tyylillä kirjoitetulle koodille tarjoaa Haskell Platformin kirjasto Control.Monad.Error johon on tarkoitus palata myöhemmin monadimuuntimien yhteydessä. Näin Maybe esittää yhtä laskentaa, joka voi myös epäonnistua. Silloin kun onkin monta laskentaa, jotka voivat myös epäonnistua, niin kyseessä on epädeterminismi (nondeterminism). Listat ovat se Monadi, joka esittää tällaisen epädeterminismin: instance Monad [] where m >>= k = concat (map k m) return x = [x] fail s = [] Epädeterministisellä laskenta-askeleella voi olla useita mahdollisia jatkovaihtohtoa, ja nämä eri vaihtoehdot esitetään listana. (>>=) sanoo laske kaikki epädeterministisen laskenta-askeleen k mahdolliset jatkovaihtoehdot jokaiselle nykyiselle vaihtoehdolle jotka ovat listana m. return luo yhden tällaisen laskennan. fail ilmoittaa, että tällä laskennalla ei ole yhtään jatkovaihtoehtoa. Listojen erikoissyntaksi [tulos osat] onkin monadisella syntaksilla 116

19 do osat return tulos kun jokainen sen osa muotoa ehto :: Bool kirjoitetaan muodossa True <- return ehto. Haskellin toteuttaa listojen erikoissyntaksin eli tämän monadin haarautuvan epädeterministisen laskennan eri vaihtoehtojen laiskana syvyyssuuntaisena läpikäyntinä. 7.4 Tilaperustaisen ohjelmoinnin monadi Monadissa IO voi siis tarvittaessa käyttää uudelleensijoitettavia muistipaikkoja ja taulukoita proseduraalista I/O-ohjelmointia varten. ghc-kirjastossa on monadi Control.Monad.ST jossa voi käyttää uudelleensijoitettavia muuttujia kirjastosta Data.STRef taulukoita kirjastosta Data.Array.ST joten tässä monadissa voi kirjoittaa sellaista proseduraalista koodia, joka ei tarvitse I/O-operaatioita. Tämän monadin ST proseduraalista koodia voi kutsua funktionaalisesta koodista, koska sen suoritusfunktio runst kapseloi kaikki sivuvaikutukset sisäänsä, jolloin sen rajapinnat ovat yhä funktionaalisia. Tämän kapseloivan suoritusfunktion tyyppi on runst :: (forall s. ST s a) -> a jossa suoritettavan laskennan tyypissä ST s on se varsinainen monadi, ja a sen vastauksen tyyppi s on eksistentiaalisesti kvantifioitu tyyppi. Täsätä tyypistä ei tiedetä yhtään mitään (koska sille ei annettu edes rajoitteita, jotka olisivat kertoneet sen metodeja) joten se voidaan vain välittää eteenpäin suoritettavan laskennan tyyppeihin. Tämä sama eksistentiaalinen tyyppiparametri s esiintyykin tämän monadin jokaisen operaation tyypissä. Esimerkiksi operaation newstref :: a -> ST s (STRef s a) tulostyyppi on monadin ST s laskenta, jonka vastaustyyppi on STRef s a eli tämän monadin uudelleensijoitettava muistipaikka, jonka sisältö on tyyppiä a. Kummassakin esiintyyy tämä s koska tämän monadin koko nimi on ST s. Tämä sama eksistentiaalinen tyyppiparametri s takaa halutun kapseloinnin käännösaikana: 117

20 Vain runst k saa suorittaa sellaisen laskennan jonka tyyppi on k :: ST s a. Samalla tämä runst kvantifioi tämän s eksistentiaalisesti tässä laskennassa k. Siis on olemassa sellainen tyyppi s joka laskennassa k.... Jos tästä laskennasta k yritetään palauttaa sellainen vastaus, jonka tyypissä a esiintyy s, niin Haskellin tyypinpäättely ei annakaan tehdä sitä, koska silloin tämä s pääsisi karkuun siitä näkyvyysalueesta k jolle runst sen määritteli. Siten s ei voi esiintyä laskennan k vastaustyypissä a. Siten laskennan k vastauksessa ei voi esiintyä esimerkiksi sen aikana luotuja uudelleensijoitettavia muistipaikkoja tai taulukoita. Otetaan esimerkiksemme seuraava ohjelmointiongelmaa: Saamme listan pareja (x,y) jotka tarkoittavat että alkioiden x ja y pitää kuulua samaan joukkoon. Mitkä nämä joukot ovat, kun alkiot pidetään erillään, ellei mikään tällainen pari vaadi niiden kuuluvan yhteen? Tämä ohjelmointiongelma esiintyy vaikkapa Kruskalin algoritmissa, jolla lasketaan suuntaamattoman verkon virittävää metsää samastuksessa joka oli tärkeä työväline esimerkiksi laskennallisessa logiikassa HM-tyypinpäättelyssä joka hyödyntää samastusta. Tämä ohjelmointionglema vaatii tietorakenteen, jossa on seuraavat operaatiot: initial joka alustaa sen siten, että jokainen alkio on aluksi yksin omassa joukossaan. union joka yhdistää ne joukot, joissa annetut alkiot x ja y nyt ovat. Siitä käytetään myös nimeä merge. find palauttaa sen joukon edustajan johon alkio z nyt kuuluu. Joukon edustaja on jokin sen alkioista. Sitä käytetään koko joukon nimenä. Kun esimerkiksi kysytään ovatko alkiot x ja y jo nyt samassa joukossa niin re ratkaistaan kysymällä, onko alkion x joukon edustaja sama kuin alkion y joukon edustaja. Tämä tietorakenne tunnetaankin nimellä union-find tai merge-find. Tämä vaikuttaa sellaiselta ohjelmointiongelmalta, jonka imperatiivinen ratkaisu on funktionaalista nopeampi: Koska imperatiivisessa ratkaisussa voidaan käyttää uudelleensijoitusta, niin siellä voidaan tiivistää hakupolku alkiosta x sen edustajaan, jotta seuraavat kyselyt sujuvat nopeammin. Tällöin saadaan ratkaisu, joka toimii askeleessa, jossa O((m + n) α(m + n)) 118

21 m on alkioiden lukumäärä n on operaatioiden union ja find lukumäärä α on erittäin hitaasti kasvava funktio. Se on Ackermannin funktion (joka kasvaa erittäin nopeasti) käänteisfunktion sukulainen. Käytännössä α(m + n) > 5 vasta kun m + n > alkeishiukkasten arvioitu lukumäärä koko maailmankaikkeudessamme... Funktionaalisessa onjelmoinnissa tämä polun tiivistäminen ei ole mahdollista, ja ainakin yksinkertaiset tietorakenneratkaisut tarvitsevat funtion α tilalla logaritmifunktion. Imperatiivisessa ratkaisussa on oleellisesti taulukko mem jossa alkiosta z 0 alkava polku mem[z 0 ] mem[z 1 ] mem[z 2 ] z 0 z 1 z 2 mem[zp] z p+1 johtaa alkion z 0 joukon edustajaan z p+1 saakka. Kun kysytään operaatiolla find alkion x joukon edustajaa, niin samalla tämä polku tiivistetään muotoon mem[z 0 ] =mem[z 1 ] =mem[z 2 ] = =mem[z p ] = z p+1 jolloin kaikkien näiden muidenkin alkioiden z 1, z 2, z 3,...,z p 1 edustajien haku operaatiolla find nopeutuvat. Operaatiota union voidaan taas tehostaa seuraavasti: Pidetään yllä jokaisessa edustajassa tietoa rank joka olisi näistä mem-linkeistä koostuvan puun korkeus ilman polkujen tiivistämistä. Tämän tiedon avulla yhdistetään aina matalamman puun juuri korkeamman puun juuren alipuuksi. Nämä juuret eli edustajat antaa siis operaatio find. Monadissa ST voimme luoda tällaisen taulukon mem ja käyttää sitä: Operaatio newarray_::(marray a e m,ix i)=> (i, i) -> m (a i e) luo taulukon tälle indeksivälille sellaisessa monadissa m jossa taulukot sallitaan. ST ja IO ovat siis sellaisia monadeja m. Tyyppiluokka Ix on ne tyypit, joita voi käyttää taulukkoindekseinä. Operaatio readarray::(marray a e m,ix i)=> a i e -> i -> m e lukee tällaisen taulukon arvon annetusta indeksistä. Operaatio writearray::(marray a e m,ix i)=> a i e -> i -> e -> m () kirjoittaa tällaisen taulukon annnettuun indeksiin annetun arvon. 119

22 module UnionFind where import Control.Monad import Control.Monad.ST import Data.Array.ST import Data.Word unions :: (Ix t) => [(t,t)] -> [[t]] unions xys = let lo = minimum xsys hi = maximum xsys xsys = xs ++ ys (xs,ys) = unzip xys in runst $ do mem <- initial lo hi sequence_ $ map (uncurry $ union mem) xys sequence_ $ map (find mem) $ range (lo,hi) memz <- getassocs mem parties <- parts lo hi sequence $ map ( \ (i,it) -> let j = case it of Rank _ -> i Ranked k -> k in do jt <- readarray parties j writearray parties j $ i:jt) memz groupies <- getelems parties return $ map reverse $ filter (not. null) groupies data Item t = Rank Word Ranked t deriving (Show) type UF s t = STArray s t (Item t) parts :: (Ix t) => t -> t -> ST s (STArray s t [t]) parts lo hi = newarray (lo,hi) [] initial :: (Ix t) => t -> t -> ST s (UF s t) initial lo hi = do mem <- newarray_ (lo,hi) sequence_ $ map (flip (writearray mem) (Rank 0)) $ range (lo,hi) return mem find :: (Ix t) => UF s t -> t -> ST s t 120

23 find mem = let finder i = do here <- readarray mem i case here of Rank r -> return i Ranked j -> do k <- finder j writearray mem i $ Ranked k return k in finder union :: (Ix t) => UF s t -> t -> t -> ST s () union mem x y = do i <- find mem x j <- find mem y when (i/=j) $ do Rank p <- readarray mem i Rank q <- readarray mem j if p<q then writearray mem i (Ranked j) else do writearray mem j (Ranked i) when (p==q) $ writearray mem i $ Rank (p+1) 121

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005 Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005 Tällä luennolla Algebralliset tietotyypit Hahmonsovitus (pattern matching) Primitiivirekursio Esimerkkinä binäärinen hakupuu Muistattehan...

Lisätiedot

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

tään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla 2.5. YDIN-HASKELL 19 tään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla kirjaimilla. Jos Γ ja ovat tyyppilausekkeita, niin Γ on tyyppilauseke. Nuoli kirjoitetaan koneella

Lisätiedot

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIEA341 Funktio-ohjelmointi 1, kevät 2008 TIEA341 Funktio-ohjelmointi 1, kevät 2008 Luento 14: Monadit Antti-Juhani Kaijanaho Jyväskylän yliopisto Tietotekniikan laitos 21. tammikuuta 2008 Tyyppien tyypit eli luonteet engl. kind tyyppinimet, kuten

Lisätiedot

Tyyppejä ja vähän muutakin. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Tyyppejä ja vähän muutakin. TIEA341 Funktio ohjelmointi 1 Syksy 2005 Tyyppejä ja vähän muutakin TIEA341 Funktio ohjelmointi 1 Syksy 2005 Viime luennolla... Haskellin alkeita pääasiassa Hello World!... ja muita tutunoloisia ohjelmia Haskellilla Haskellin voima on kuitenkin

Lisätiedot

5.2.5 Konstruktoriluokat Edellisessä esimerkissä määrittelimme oman tyyppiluokan Isqrt jonka jäsenet olivat tyyppejä (kuten Int, Integer, Word,...).

5.2.5 Konstruktoriluokat Edellisessä esimerkissä määrittelimme oman tyyppiluokan Isqrt jonka jäsenet olivat tyyppejä (kuten Int, Integer, Word,...). 5.2.5 Konstruktoriluokat Edellisessä esimerkissä määrittelimme oman tyyppiluokan Isqrt jonka jäsenet olivat tyyppejä (kuten Int, Integer, Word,...). Voimme määritellä tyyppiluokkia myös tyyppikonstruktoreille

Lisätiedot

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

Laajennetaan vielä Ydin-Haskellia ymmärtämään vakiomäärittelyt. Määrittely on muotoa 2.6. TIETOKONE LASKIMENA 23 Edellä esitetty Ydin-Haskell on hyvin lähellä sitä kieltä, jota GHCi (Glasgow Haskell Compiler, Interactive) sekä muut Haskell-järjestelmät suostuvat ymmärtämään. Esimerkiksi:

Lisätiedot

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

Tyyppiluokat II konstruktoriluokat, funktionaaliset riippuvuudet. TIES341 Funktio-ohjelmointi 2 Kevät 2006 Tyyppiluokat II konstruktoriluokat, funktionaaliset riippuvuudet TIES341 Funktio-ohjelmointi 2 Kevät 2006 Alkuperäislähteitä Philip Wadler & Stephen Blott: How to make ad-hoc polymorphism less ad-hoc,

Lisätiedot

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset 815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 6 Vastaukset Harjoituksen aiheena on funktionaalinen ohjelmointi Scheme- ja Haskell-kielillä. Voit suorittaa ohjelmat osoitteessa https://ideone.com/

Lisätiedot

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIEA341 Funktio-ohjelmointi 1, kevät 2008 TIEA341 Funktio-ohjelmointi 1, kevät 2008 Luento 3 Antti-Juhani Kaijanaho Jyväskylän yliopisto Tietotekniikan laitos 14. tammikuuta 2008 Viittausten läpinäkyvyyden 1 periaatteet 1. Lausekkeen arvo ei riipu

Lisätiedot

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIEA341 Funktio-ohjelmointi 1, kevät 2008 TIEA341 Funktio-ohjelmointi 1, kevät 2008 Luento 5 Ympärysmitta. Puut. Antti-Juhani Kaijanaho Jyväskylän yliopisto Tietotekniikan laitos 21. tammikuuta 2008 CASE: YMPÄRYSMITTA Lasketaan kuvioiden ympärysmittoja

Lisätiedot

Monadeja siellä, monadeja täällä... monadeja kaikkialla? TIES341 Funktio ohjelmointi 2 Kevät 2006

Monadeja siellä, monadeja täällä... monadeja kaikkialla? TIES341 Funktio ohjelmointi 2 Kevät 2006 Monadeja siellä, monadeja täällä... monadeja kaikkialla? TIES341 Funktio ohjelmointi 2 Kevät 2006 Materiaalia Paras verkkomatsku: http://www.nomaware.com/monads/html/ Komentoanalogiasta vielä Monadityypin

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 1.4.2009 T-106.1208 Ohjelmoinnin perusteet Y 1.4.2009 1 / 56 Tentti Ensimmäinen tenttimahdollisuus on pe 8.5. klo 13:00 17:00 päärakennuksessa. Tämän jälkeen

Lisätiedot

Luku 3. Listankäsittelyä. 3.1 Listat

Luku 3. Listankäsittelyä. 3.1 Listat Luku 3 Listankäsittelyä Funktio-ohjelmoinnin tärkein yksittäinen tietorakenne on lista. Listankäsittely on paitsi käytännöllisesti oleellinen aihe, se myös valaisee funktio-ohjelmoinnin ideaa. 3.1 Listat

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 2.3.2009 T-106.1208 Ohjelmoinnin perusteet Y 2.3.2009 1 / 28 Puhelinluettelo, koodi def lue_puhelinnumerot(): print "Anna lisattavat nimet ja numerot." print

Lisätiedot

815338A Ohjelmointikielten periaatteet 2014-2015. Harjoitus 7 Vastaukset

815338A Ohjelmointikielten periaatteet 2014-2015. Harjoitus 7 Vastaukset 815338A Ohjelmointikielten periaatteet 2014-2015. Harjoitus 7 Vastaukset Harjoituksen aiheena on funktionaalinen ohjelmointi Scheme- ja Haskell-kielillä. Voit suorittaa ohjelmat osoitteessa https://ideone.com/

Lisätiedot

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIEA341 Funktio-ohjelmointi 1, kevät 2008 TIEA341 Funktio-ohjelmointi 1, kevät 2008 Luento 4 Antti-Juhani Kaijanaho Jyväskylän yliopisto Tietotekniikan laitos 17. tammikuuta 2008 Modulin viimeistelyä module Shape ( Shape ( Rectangle, E l l i p

Lisätiedot

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIEA341 Funktio-ohjelmointi 1, kevät 2008 TIEA341 Funktio-ohjelmointi 1, kevät 2008 Luento 9 Kombinaattoreista Antti-Juhani Kaijanaho Jyväskylän yliopisto Tietotekniikan laitos 21. tammikuuta 2008 Currying Haskell-funktio ottaa aina vain yhden

Lisätiedot

5.5 Jäsenninkombinaattoreista

5.5 Jäsenninkombinaattoreista 5.5. JÄSENNINKOMBINAATTOREISTA 67 type Env α = FiniteMap String α data EnvT m α = MkE (Env Integer m (Env Integer, α)) instance Transformer EnvT where promote mp = MkE $ λenv mp λr return $(env, r) instance

Lisätiedot

main :: IO () main = interact (concatmap ((++"\n"). reverse). lines)

main :: IO () main = interact (concatmap ((++\n). reverse). lines) saa syötteenään oletussyötevirran stdin koko (jäljellä olevan) sisällön laiskasti luettavana merkkijonona antaa tulosteensa toisena merkkijonona jota se voi rytmittää rivinvaihdoilla. Esimerkiksi: module

Lisätiedot

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b Pythonin Kertaus Cse-a1130 Tietotekniikka Sovelluksissa Versio 0.01b Listat 1/2 esimerkkejä listan peruskäytöstä. > lista=['kala','kukko','kissa','koira'] ['kala','kukko','kissa','koira'] >lista.append('kana')

Lisätiedot

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

Tämän vuoksi kannattaa ottaa käytännöksi aina kirjoittaa uuden funktion tyyppi näkyviin, ennen kuin alkaa sen määritemää kirjoittamaan. 3.1. LISTAT 35 destaan pisteittäisesti: init :: [α] [α] init (x : []) = [] init (x : xs) = x : init xs Varuskirjastoon kuuluu myös funktiot take ja drop, jotka ottavat tai tiputtavat pois, funktiosta riippuen,

Lisätiedot

Esimerkki: Laskin (alkua) TIEA341 Funktio ohjelmointi 1 Syksy 2005

Esimerkki: Laskin (alkua) TIEA341 Funktio ohjelmointi 1 Syksy 2005 Esimerkki: Laskin (alkua) TIEA341 Funktio ohjelmointi 1 Syksy 2005 Esimerkki: Laskin Liukulukulaskentaa Yhteen, vähennys, kerto ja jakolaskut Syötteenä laskutehtävä, tulosteena tulos tai virheilmoitus

Lisätiedot

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5) Alkuarvot ja tyyppimuunnokset (1/5) Aiemmin olemme jo antaneet muuttujille alkuarvoja, esimerkiksi: int luku = 123; Alkuarvon on oltava muuttujan tietotyypin mukainen, esimerkiksi int-muuttujilla kokonaisluku,

Lisätiedot

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIEA341 Funktio-ohjelmointi 1, kevät 2008 TIEA34 Funktio-ohjelmointi, kevät 2008 Luento 3 Antti-Juhani Kaijanaho Jyväskylän yliopisto Tietotekniikan laitos 2. tammikuuta 2008 Ydin-Haskell: Syntaksi Lausekkeita (e) ovat: nimettömät funktiot: \x

Lisätiedot

Java-kielen perusteet

Java-kielen perusteet Java-kielen perusteet Tunnus, varattu sana, kommentti Muuttuja, alkeistietotyyppi, merkkijono, literaalivakio, nimetty vakio Tiedon merkkipohjainen tulostaminen 1 Tunnus Java tunnus Java-kirjain Java-numero

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 2.3.2011 T-106.1208 Ohjelmoinnin perusteet Y 2.3.2011 1 / 39 Kertausta: tiedoston avaaminen Kun ohjelma haluaa lukea tai kirjoittaa tekstitiedostoon, on ohjelmalle

Lisätiedot

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIEA341 Funktio-ohjelmointi 1, kevät 2008 TIEA341 Funktio-ohjelmointi 1, kevät 2008 Luento 10 Todistamisesta Antti-Juhani Kaijanaho Jyväskylän yliopisto Tietotekniikan laitos 21. tammikuuta 2008 Samuuden todistaminen usein onnistuu ihan laskemalla

Lisätiedot

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä 12.1 12.2 12.3 12.4

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä 12.1 12.2 12.3 12.4 Sisällys 12. Näppäimistöltä lukeminen Arvojen lukeminen näppäimistöltä yleisesti. Arvojen lukeminen näppäimistöltä Java-kielessä.. Luetun arvon tarkistaminen. Tietovirrat ja ohjausmerkit. Scanner-luokka.

Lisätiedot

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä Ohjelmoinnin peruskurssien laaja oppimäärä Luento 7: Funktionaalista ohjelmointia (mm. SICP 3.5) Riku Saikkonen 13. 11. 2012 Sisältö 1 Laiskaa laskentaa: delay ja force 2 Funktionaalinen I/O 3 Funktionaalista

Lisätiedot

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta C++ - perusteet Java-osaajille luento 5/7: operaattoreiden ylikuormitus, oliotaulukko, parametrien oletusarvot, komentoriviparametrit, constant, inline, Operaattoreiden ylikuormitus Operaattoreiden kuormitus

Lisätiedot

Luku 4. Tietorakenteet funktio-ohjelmoinnissa. 4.1 Äärelliset kuvaukset

Luku 4. Tietorakenteet funktio-ohjelmoinnissa. 4.1 Äärelliset kuvaukset Luku 4 Tietorakenteet funktio-ohjelmoinnissa Koska funktio-ohjelmoinnissa ei käytetä tuhoavaa päivitystä (sijoituslausetta ja sen johdannaisia), eivät läheskään kaikki valtavirtaohjelmoinnista tutut tietorakenteet

Lisätiedot

Haskell ohjelmointikielen tyyppijärjestelmä

Haskell ohjelmointikielen tyyppijärjestelmä Haskell ohjelmointikielen tyyppijärjestelmä Sakari Jokinen Helsinki 19. huhtikuuta 2004 Ohjelmointikielten perusteet - seminaarityö HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos 1 Johdanto 1 Tyyppien

Lisätiedot

12. Näppäimistöltä lukeminen 12.1

12. Näppäimistöltä lukeminen 12.1 12. Näppäimistöltä lukeminen 12.1 Sisällys Arvojen lukeminen näppäimistöltä yleisesti. Arvojen lukeminen näppäimistöltä Java-kielessä. In-luokka. Luetun arvon tarkistaminen. Tietovirrat ja ohjausmerkit.

Lisätiedot

ITKP102 Ohjelmointi 1 (6 op)

ITKP102 Ohjelmointi 1 (6 op) ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 22. huhtikuuta 2016 Vastaa kaikkiin tehtäviin. Tee jokainen tehtävä erilliselle konseptiarkille! Kirjoittamasi luokat, funktiot ja aliohjelmat

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 16.3.2009 T-106.1208 Ohjelmoinnin perusteet Y 16.3.2009 1 / 40 Kertausta: tiedostosta lukeminen Aluksi käsiteltävä tiedosto pitää avata: tiedostomuuttuja = open("teksti.txt","r")

Lisätiedot

Abstraktit tietotyypit. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Abstraktit tietotyypit. TIEA341 Funktio ohjelmointi 1 Syksy 2005 Abstraktit tietotyypit TIEA341 Funktio ohjelmointi 1 Syksy 2005 Data abstraktio Abstraktio on ohjelmoinnin tärkein väline Data abstraktio abstrahoi dataa Abstrakti tietotyyppi Koostuu kolmesta asiasta:

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 28.2.2011 T-106.1208 Ohjelmoinnin perusteet Y 28.2.2011 1 / 46 Ohjelmointiprojektin vaiheet 1. Määrittely 2. Ohjelman suunnittelu (ohjelman rakenne ja ohjelman

Lisätiedot

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

AS-0.1103 C-ohjelmoinnin peruskurssi 2013: C-kieli käytännössä ja erot Pythoniin AS-0.1103 C-ohjelmoinnin peruskurssi 2013: C-kieli käytännössä ja erot Pythoniin Raimo Nikkilä Aalto-yliopiston sähkötekniikan korkeakoulu - Automaation tietotekniikan tutkimusryhmä 17. tammikuuta 2013

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 25.2.2009 T-106.1208 Ohjelmoinnin perusteet Y 25.2.2009 1 / 34 Syötteessä useita lukuja samalla rivillä Seuraavassa esimerkissä käyttäjä antaa useita lukuja samalla

Lisätiedot

ITKP102 Ohjelmointi 1 (6 op)

ITKP102 Ohjelmointi 1 (6 op) ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 7. huhtikuuta 2017 Vastaa kaikkiin tehtäviin. Tee jokainen tehtävä erilliselle konseptiarkille. Kirjoittamasi luokat, funktiot ja aliohjelmat

Lisätiedot

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä Ohjelmoinnin peruskurssien laaja oppimäärä Luento 2: SICP kohdat 22.2.3 Riku Saikkonen 2. 11. 2010 Sisältö 1 Linkitetyt listat 2 Listaoperaatioita 3 Listarakenteet 4 Gambit-C:n Scheme-debuggeri Linkitetyt

Lisätiedot

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset 815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 2 vastaukset Harjoituksen aiheena on BNF-merkinnän käyttö ja yhteys rekursiivisesti etenevään jäsentäjään. Tehtävä 1. Mitkä ilmaukset seuraava

Lisätiedot

Hakemistojen sisällöt säilötään linkitetyille listalle.

Hakemistojen sisällöt säilötään linkitetyille listalle. Harjoitustyö 1 Harjoitustyö Tehtävä: ohjelmoi Java-kielellä komentoikkunaa (komentotulkkia, komentoriviä) simuloiva olioperustainen ohjelma. Hakemistojen sisällöt säilötään linkitetyille listalle. Työ

Lisätiedot

Sisällys. 3. Muuttujat ja operaatiot. Muuttujat ja operaatiot. Muuttujat. Operaatiot. Imperatiivinen laskenta. Muuttujat. Esimerkkejä: Operaattorit.

Sisällys. 3. Muuttujat ja operaatiot. Muuttujat ja operaatiot. Muuttujat. Operaatiot. Imperatiivinen laskenta. Muuttujat. Esimerkkejä: Operaattorit. 3. Muuttujat ja operaatiot Sisällys Imperatiivinen laskenta. Muuttujat. Nimi ja arvo. Muuttujan nimeäminen. Muuttujan tyyppi.. Operandit. Arvon sijoitus muuttujaan. Aritmeettiset operaattorit. Arvojen

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 20.1.2010 T-106.1208 Ohjelmoinnin perusteet Y 20.1.2010 1 / 40 Arvon pyytäminen käyttäjältä Käyttäjän antaman arvon voi lukea raw_input-käskyllä. Käskyn sulkujen

Lisätiedot

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIEA341 Funktio-ohjelmointi 1, kevät 2008 TIEA341 Funktio-ohjelmointi 1, kevät 2008 Luento 11 Antti-Juhani Kaijanaho Jyväskylän yliopisto Tietotekniikan laitos 21. tammikuuta 2008 Listakomprehensio Uusi tapa luoda (ja muokata) listoja: [ lauseke

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 21.1.2009 T-106.1208 Ohjelmoinnin perusteet Y 21.1.2009 1 / 32 Tyypeistä Monissa muissa ohjelmointikielissä (esim. Java ja C) muuttujat on määriteltävä ennen

Lisätiedot

3. Muuttujat ja operaatiot 3.1

3. Muuttujat ja operaatiot 3.1 3. Muuttujat ja operaatiot 3.1 Sisällys Imperatiivinen laskenta. Muuttujat. Nimi ja arvo. Muuttujan nimeäminen. Muuttujan tyyppi. Operaattorit. Operandit. Arvon sijoitus muuttujaan. Aritmeettiset operaattorit.

Lisätiedot

8. Näppäimistöltä lukeminen 8.1

8. Näppäimistöltä lukeminen 8.1 8. Näppäimistöltä lukeminen 8.1 Sisällys Arvojen lukeminen näppäimistöltä Java-kielessä. In-luokka. In-luokka, käännös ja tulkinta Scanner-luokka. 8.2 Yleistä Näppäimistöltä annettujen arvojen (syötteiden)

Lisätiedot

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

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit IDL - proseduurit 25. huhtikuuta 2017 Viimeksi käsiteltiin IDL:n interaktiivista käyttöä, mutta tämä on hyvin kömpelöä monimutkaisempia asioita tehtäessä. IDL:llä on mahdollista tehdä ns. proseduuri-tiedostoja,

Lisätiedot

8. Näppäimistöltä lukeminen 8.1

8. Näppäimistöltä lukeminen 8.1 8. Näppäimistöltä lukeminen 8.1 Sisällys Arvojen lukeminen näppäimistöltä Java-kielessä. In-luokka. In-luokka, käännös ja tulkinta Scanner-luokka. 8.2 Yleistä Näppäimistöltä annettujen arvojen (syötteiden)

Lisätiedot

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

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014 18. syyskuuta 2014 IDL - proseduurit Viimeksi käsiteltiin IDL:n interaktiivista käyttöä, mutta tämä on hyvin kömpelöä monimutkaisempia asioita tehtäessä. IDL:llä on mahdollista tehdä ns. proseduuri-tiedostoja,

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 1.3.2010 T-106.1208 Ohjelmoinnin perusteet Y 1.3.2010 1 / 36 Monikko Monikko (engl. tuple) muistuttaa listaa, mutta monikon sisältöä ei voi muuttaa sen jälkeen,

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 16.2.2010 T-106.1208 Ohjelmoinnin perusteet Y 16.2.2010 1 / 41 Kännykkäpalautetteen antajia kaivataan edelleen! Ilmoittaudu mukaan lähettämällä ilmainen tekstiviesti

Lisätiedot

Zeon PDF Driver Trial

Zeon PDF Driver Trial Matlab-harjoitus 2: Kuvaajien piirto, skriptit ja funktiot. Matlabohjelmoinnin perusteita Numeerinen integrointi trapezoidaalimenetelmällä voidaan tehdä komennolla trapz. Esimerkki: Vaimenevan eksponentiaalin

Lisätiedot

C-kielessä taulukko on joukko peräkkäisiä muistipaikkoja, jotka kaikki pystyvät tallettamaan samaa tyyppiä olevaa tietoa.

C-kielessä taulukko on joukko peräkkäisiä muistipaikkoja, jotka kaikki pystyvät tallettamaan samaa tyyppiä olevaa tietoa. Taulukot C-kielessä taulukko on joukko peräkkäisiä muistipaikkoja, jotka kaikki pystyvät tallettamaan samaa tyyppiä olevaa tietoa. Taulukon muuttujilla (muistipaikoilla) on yhteinen nimi. Jokaiseen yksittäiseen

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 17.2.2010 T-106.1208 Ohjelmoinnin perusteet Y 17.2.2010 1 / 41 Sanakirja Monissa sovelluksissa on tallennettava rakenteeseen avain arvo-pareja. Myöhemmin rakenteesta

Lisätiedot

811120P Diskreetit rakenteet

811120P Diskreetit rakenteet 811120P Diskreetit rakenteet 2016-2017 1. Algoritmeista 1.1 Algoritmin käsite Algoritmi keskeinen laskennassa Määrittelee prosessin, joka suorittaa annetun tehtävän Esimerkiksi Nimien järjestäminen aakkosjärjestykseen

Lisätiedot

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

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 30. marraskuuta 2015 TIEA241 Automaatit ja kieliopit, syksy 2015 Antti-Juhani Kaijanaho TIETOTEKNIIKAN LAITOS 30. marraskuuta 2015 Sisällys t Väitöstilaisuus 4.12.2015 kello 12 vanhassa juhlasalissa S212 saa tulla 2 demoruksia

Lisätiedot

Tietorakenteet ja algoritmit - syksy 2015 1

Tietorakenteet ja algoritmit - syksy 2015 1 Tietorakenteet ja algoritmit - syksy 2015 1 Tietorakenteet ja algoritmit - syksy 2015 2 Tietorakenteet ja algoritmit Johdanto Ari Korhonen Tietorakenteet ja algoritmit - syksy 2015 1. JOHDANTO 1.1 Määritelmiä

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 11.2.2009 T-106.1208 Ohjelmoinnin perusteet Y 11.2.2009 1 / 33 Kertausta: listat Tyhjä uusi lista luodaan kirjoittamalla esimerkiksi lampotilat = [] (jolloin

Lisätiedot

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä Ohjelmoinnin peruskurssien laaja oppimäärä Luento 6: Funktionaalista ohjelmointia: todistamisesta, virrat ja I/O, hahmonsovitus (mm. SICP 3.5) Riku Saikkonen 8. 11. 2011 Sisältö 1 Vähän funktionaalisten

Lisätiedot

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti: 1 (7) Tiedon lukeminen näppäimistöltä Scanner-luokan avulla Miten ohjelma saa käyttöönsä käyttäjän kirjoittamaa tekstiä? Järjestelmässä on olemassa ns. syöttöpuskuri näppäimistöä varten. Syöttöpuskuri

Lisätiedot

Ohjelmointiharjoituksia Arduino-ympäristössä

Ohjelmointiharjoituksia Arduino-ympäristössä Ohjelmointiharjoituksia Arduino-ympäristössä Yleistä Arduino-sovelluksen rakenne Syntaksi ja käytännöt Esimerkki ohjelman rakenteesta Muuttujat ja tietotyypit Tietotyypit Esimerkkejä tietotyypeistä Ehtolauseet

Lisätiedot

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä Matti Luukkainen 10.12.2009 Tässä esitetty esimerkki on mukaelma ja lyhennelmä Robert Martinin kirjasta Agile and Iterative Development löytyvästä

Lisätiedot

Taas laskin. TIES341 Funktio ohjelmointi 2 Kevät 2006

Taas laskin. TIES341 Funktio ohjelmointi 2 Kevät 2006 Taas laskin TIES341 Funktio ohjelmointi 2 Kevät 2006 Rakennepuutyyppi data Term = C Rational T F V String Term :+: Term Term : : Term Term :*: Term Term :/: Term Term :==: Term Term :/=: Term Term :

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 15.3.2010 T-106.1208 Ohjelmoinnin perusteet Y 15.3.2010 1 / 56 Tiedostoista: tietojen tallentaminen ohjelman suorituskertojen välillä Monissa sovelluksissa ohjelman

Lisätiedot

Rekursiolause. Laskennan teorian opintopiiri. Sebastian Björkqvist. 23. helmikuuta Tiivistelmä

Rekursiolause. Laskennan teorian opintopiiri. Sebastian Björkqvist. 23. helmikuuta Tiivistelmä Rekursiolause Laskennan teorian opintopiiri Sebastian Björkqvist 23. helmikuuta 2014 Tiivistelmä Työssä käydään läpi itsereplikoituvien ohjelmien toimintaa sekä esitetään ja todistetaan rekursiolause,

Lisätiedot

Ohjelmointitaito (ict1td002, 12 op) Kevät 2008. 1. Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen raine.kauppinen@haaga-helia.

Ohjelmointitaito (ict1td002, 12 op) Kevät 2008. 1. Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen raine.kauppinen@haaga-helia. Ohjelmointitaito (ict1td002, 12 op) Kevät 2008 Raine Kauppinen raine.kauppinen@haaga-helia.fi 1. Java-ohjelmoinnin alkeita Tietokoneohjelma Java-kieli ja Eclipse-ympäristö Java-ohjelma ja ohjelmaluokka

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 3.3.2010 T-106.1208 Ohjelmoinnin perusteet Y 3.3.2010 1 / 44 Kertausta: tiedoston avaaminen Kun ohjelma haluaa lukea tai kirjoittaa tekstitiedostoon, on ohjelmalle

Lisätiedot

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

2.4 Normaalimuoto, pohja ja laskentajärjestys 2.4. NORMAALIMUOTO, POHJA JA LASKENTAJÄRJESTYS 13 2.4. NORMAALIMUOTO, POHJA JA LASKENTAJÄRJESTYS 13 Toisinaan voi olla syytä kirjoittaa α- tai β-kirjain yhtäsuuruusmerkin yläpuolelle kertomaan, mitä muunnosta käytetään. Esimerkki 4 1. (λx.x)y β = y 2.

Lisätiedot

5.3 Laskimen muunnelmia 5.3. LASKIMEN MUUNNELMIA 57

5.3 Laskimen muunnelmia 5.3. LASKIMEN MUUNNELMIA 57 5.3. LASKIMEN MUUNNELMIA 57 Samaan sarjaan kuuluu seuraavakin funktio, jonka määritelmä esittelee muutenkin hyödyllisen tavan kirjoittaa ohjelmia: getline :: IO String getline = getchar λc case c of \n

Lisätiedot

Sisältö. 22. Taulukot. Yleistä. Yleistä

Sisältö. 22. Taulukot. Yleistä. Yleistä Sisältö 22. Taulukot Yleistä. Esittely ja luominen. Alkioiden käsittely. Kaksiulotteinen taulukko. Taulukko metodin parametrina. Taulukko ja HelloWorld-ohjelma. Taulukko paluuarvona. 22.1 22.2 Yleistä

Lisätiedot

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

Imperatiivisen ohjelmoinnin peruskäsitteet. Meidän käyttämän pseudokielen lauseiden syntaksi Imperatiivisen ohjelmoinnin peruskäsitteet muuttuja muuttujissa oleva data voi olla yksinkertaista eli primitiivistä (esim. luvut ja merkit) tai rakenteista jolloin puhutaan tietorakenteista. puhuttaessa

Lisätiedot

Sisältö. 2. Taulukot. Yleistä. Yleistä

Sisältö. 2. Taulukot. Yleistä. Yleistä Sisältö 2. Taulukot Yleistä. Esittely ja luominen. Alkioiden käsittely. Kaksiulotteinen taulukko. Taulukko operaation parametrina. Taulukko ja HelloWorld-ohjelma. Taulukko paluuarvona. 2.1 2.2 Yleistä

Lisätiedot

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

Demo 7 ( ) Antti-Juhani Kaijanaho. 9. joulukuuta 2005 Demo 7 (14.12.2005) Antti-Juhani Kaijanaho 9. joulukuuta 2005 Liitteenä muutama esimerkki Ydin-Haskell-laskuista. Seuraavassa on enemmän kuin 12 nimellistä tehtävää; ylimääräiset ovat bonustehtäviä, joilla

Lisätiedot

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä Ohjelmoinnin peruskurssien laaja oppimäärä Luento 6: Rajoite-esimerkki, funktionaalista ohjelmointia (mm. SICP 3.3.5, 3.5) Riku Saikkonen 8. 11. 2012 Sisältö 1 SICP 3.3.5 esimerkki: rajoitteiden vyörytysjärjestelmä

Lisätiedot

Ohjelmoinnin jatkokurssi, kurssikoe 28.4.2014

Ohjelmoinnin jatkokurssi, kurssikoe 28.4.2014 Ohjelmoinnin jatkokurssi, kurssikoe 28.4.2014 Kirjoita jokaiseen palauttamaasi konseptiin kurssin nimi, kokeen päivämäärä, oma nimi ja opiskelijanumero. Vastaa kaikkiin tehtäviin omille konsepteilleen.

Lisätiedot

12. Javan toistorakenteet 12.1

12. Javan toistorakenteet 12.1 12. Javan toistorakenteet 12.1 Sisällys Yleistä toistorakenteista. Laskurimuuttujat. While-, do-while- ja for-lauseet. Laskuri- ja lippumuuttujat. Tyypillisiä ohjelmointivirheitä. Silmukan rajat asetettu

Lisätiedot

11. Javan toistorakenteet 11.1

11. Javan toistorakenteet 11.1 11. Javan toistorakenteet 11.1 Sisällys Laskuri- ja lippumuuttujat. Sisäkkäiset silmukat. Tyypillisiä ohjelmointivirheitä: Silmukan rajat asetettu kierroksen verran väärin. Ikuinen silmukka. Silmukoinnin

Lisätiedot

T Syksy 2004 Logiikka tietotekniikassa: perusteet Laskuharjoitus 7 (opetusmoniste, kappaleet )

T Syksy 2004 Logiikka tietotekniikassa: perusteet Laskuharjoitus 7 (opetusmoniste, kappaleet ) T-79144 Syksy 2004 Logiikka tietotekniikassa: perusteet Laskuharjoitus 7 (opetusmoniste, kappaleet 11-22) 26 29102004 1 Ilmaise seuraavat lauseet predikaattilogiikalla: a) Jokin porteista on viallinen

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 9.2.2009 T-106.1208 Ohjelmoinnin perusteet Y 9.2.2009 1 / 35 Listat Esimerkki: halutaan kirjoittaa ohjelma, joka lukee käyttäjältä 30 lämpötilaa. Kun lämpötilat

Lisätiedot

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin.

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin. 2. Ohjausrakenteet Ohjausrakenteiden avulla ohjataan ohjelman suoritusta. peräkkäisyys valinta toisto Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet

Lisätiedot

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä Ohjelmoinnin peruskurssien laaja oppimäärä Luento 5: Sijoituslause, SICP-oliot, todistamisesta (mm. SICP 33.1.3, 3.33.3.2) Riku Saikkonen 7. 11. 2011 Sisältö 1 Muuttujan arvon muuttaminen: set! 2 SICP-oliot

Lisätiedot

Tutoriaaliläsnäoloista

Tutoriaaliläsnäoloista Tutoriaaliläsnäoloista Tutoriaaliläsnäolokierroksella voi nyt täyttää anomuksen läsnäolon merkitsemisestä Esim. tagi ei toiminut, korvavaltimon leikkaus, yms. Hyväksyn näitä omaa harkintaa käyttäen Tarkoitus

Lisätiedot

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

Se mistä tilasta aloitetaan, merkitään tyhjästä tulevalla nuolella. Yllä olevassa esimerkissä aloitustila on A. Tehtävä. Tämä tehtävä on aineistotehtävä, jossa esitetään ensin tehtävän teoria. Sen jälkeen esitetään neljä kysymystä, joissa tätä teoriaa pitää soveltaa. Mitään aikaisempaa tehtävän aihepiirin tuntemusta

Lisätiedot

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1 Ohjelmoinnin peruskurssi Y1 CSE-A1111 21.9.2015 CSE-A1111 Ohjelmoinnin peruskurssi Y1 21.9.2015 1 / 25 Mahdollisuus antaa luentopalautetta Goblinissa vasemmassa reunassa olevassa valikossa on valinta Luentopalaute.

Lisätiedot

Luku 6. Dynaaminen ohjelmointi. 6.1 Funktion muisti

Luku 6. Dynaaminen ohjelmointi. 6.1 Funktion muisti Luku 6 Dynaaminen ohjelmointi Dynaamisessa ohjelmoinnissa on ideana jakaa ongelman ratkaisu pienempiin osaongelmiin, jotka voidaan ratkaista toisistaan riippumattomasti. Jokaisen osaongelman ratkaisu tallennetaan

Lisätiedot

815338A Ohjelmointikielten periaatteet Harjoitus 4 vastaukset

815338A Ohjelmointikielten periaatteet Harjoitus 4 vastaukset 815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 4 vastaukset Harjoituksen aiheena ovat imperatiivisten kielten lauseisiin, lausekkeisiin ja aliohjelmiin liittyvät kysymykset. Tehtävä 1. Mitä

Lisätiedot

7/20: Paketti kasassa ensimmäistä kertaa

7/20: Paketti kasassa ensimmäistä kertaa Ohjelmointi 1 / syksy 2007 7/20: Paketti kasassa ensimmäistä kertaa Paavo Nieminen nieminen@jyu.fi Tietotekniikan laitos Informaatioteknologian tiedekunta Jyväskylän yliopisto Ohjelmointi 1 / syksy 2007

Lisätiedot

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma. 2. Taulukot 2.1 Sisältö Yleistä. Esittely ja luominen. Alkioiden käsittely. Kaksiulotteinen taulukko. Taulukko operaation parametrina. Taulukko ja HelloWorld-ohjelma. Taulukko paluuarvona. 2.2 Yleistä

Lisätiedot

A274101 TIETORAKENTEET JA ALGORITMIT

A274101 TIETORAKENTEET JA ALGORITMIT A274101 TIETORAKENTEET JA ALGORITMIT PERUSTIETORAKENTEET LISTA, PINO, JONO, PAKKA ABSTRAKTI TIETOTYYPPI Tietotyyppi on abstrakti, kun se on määritelty (esim. matemaattisesti) ottamatta kantaa varsinaiseen

Lisätiedot

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari 1 1. JOHDANTO 1.1 Määritelmiä 1.2 Tietorakenteen ja algoritmin valinta 1.3 Algoritmit ja tiedon määrä 1.4 Tietorakenteet ja toiminnot 1.5 Esimerkki:

Lisätiedot

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä Ohjelmoinnin peruskurssien laaja oppimäärä Luento 3: Funktionaalinen listankäsittely ja listankäsittelyoperaatiot (mm. SICP 22.2.3) Riku Saikkonen 31. 10. 2011 Sisältö 1 Linkitetyt listat 2 Listarakenteet

Lisätiedot

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

Koka. Ryhmä 11. Juuso Tapaninen, Akseli Karvinen. 1. Taustoja 2. Kielen filosofia ja paradigmat 3. Kielen syntaksia ja vertailua JavaScriptiin Lähteet Koka Ryhmä 11 Juuso Tapaninen, Akseli Karvinen 1. Taustoja 2. Kielen filosofia ja paradigmat 3. Kielen syntaksia ja vertailua JavaScriptiin Lähteet 1 1. Taustoja Koka on Daan Leijenin ja Microsoft:n kehittämä

Lisätiedot

Java kahdessa tunnissa. Jyry Suvilehto

Java kahdessa tunnissa. Jyry Suvilehto Java kahdessa tunnissa Jyry Suvilehto Ohjelma Ohjelmointiasioita alkeista nippelitietoon n. 45 min Tauko 10 min Oliot, luokat ja muut kummajaiset n. 45 min Kysykää Sisältöä ei oikeasti ole 2x45 min täytteeksi,

Lisätiedot

Hahmon etsiminen syotteesta (johdatteleva esimerkki)

Hahmon etsiminen syotteesta (johdatteleva esimerkki) Hahmon etsiminen syotteesta (johdatteleva esimerkki) Unix-komennolla grep hahmo [ tiedosto ] voidaan etsia hahmon esiintymia tiedostosta (tai syotevirrasta): $ grep Kisaveikot SM-tulokset.txt $ ps aux

Lisätiedot

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1 Ohjelmoinnin peruskurssi Y1 CSE-A1111 30.9.2015 CSE-A1111 Ohjelmoinnin peruskurssi Y1 30.9.2015 1 / 27 Mahdollisuus antaa luentopalautetta Goblinissa vasemmassa reunassa olevassa valikossa on valinta Luentopalaute.

Lisätiedot

Java-kielen perusteita

Java-kielen perusteita Java-kielen perusteita valintalauseet 1 Johdantoa kontrollirakenteisiin Tähän saakka ohjelmissa on ollut vain peräkkäisyyttä eli lauseet on suoritettu peräkkäin yksi kerrallaan Tarvitsemme myös valintaa

Lisätiedot

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

Luku 5. Monadit. 5.1 Siirrännän ongelma Luku 5 Monadit There are lots of books about functional programming in Haskell. They tend to concentrate on the beautiful core of functional programming: higher order functions, algebraic data types, polymorphic

Lisätiedot