5.1 Tyyppiparametrit. Nyt lisäämme parametrit myös data-määrittelyihin: data Nimi tp 1 tp 2 tp 3... tp k =...

Koko: px
Aloita esitys sivulta:

Download "5.1 Tyyppiparametrit. Nyt lisäämme parametrit myös data-määrittelyihin: data Nimi tp 1 tp 2 tp 3... tp k =..."

Transkriptio

1 5.1 Tyyppiparametrit Nyt lisäämme parametrit myös data-määrittelyihin: data Nimi tp 1 tp 2 tp 3... tp k =... Lisäämme ne myös type- ja newtype-määrittelyihin. Nämäkin parametrit tp i kirjoitetaan pienellä alkukirjaimella futen funktioidenkin parametrit. Sitten voimme käyttää näitä tyyppiparametreja tp i kuten tyypinnimiä tämän datamäärittelyn haaroissa. Siis eri haarojen kenttien tyypeissä. Intuitio on, että Nimi Ty 1 Ty 2 Ty 3... Ty k on sellainen uusi tyyppi, jossa tämä annettu tyyppi Ty i esiintyy niissä kohdissa, joissa data-määrittelyn haarassa esiintyi sitä vastaava tyyppiparametri tp i. Siis tällainen tyyppiparametrisoitu Nimi ei olekaan enää itsenään minkään tyypin nimi, vaan nimi funktiolle joka saatuaan jotkut tyypit Ty i synnyttää niistä tämän uuden tyypin Nimi Ty 1 Ty 2 Ty 3... Ty k. Siksi sitä kutsutaankin tyyppikonstruktoriksi. Otetaan esimerkiksemme aiempi hakupuumme, johon lisätään uusi kenttä nimeltään tieto. Ideana on, että sinne voisi tallettaa tähän avaimeen liittyvän tietoalkion, ja näin saada hakupuustamme sanakirjan (dictionary): Tietorakenteen, jolta voisi kysyä mikä on tätä avainarvoa x vastaava talletettu tietoalkio? Mikä sen tietoalkiokentän tyyppi pitäisi olla? Joskus voimme tarvita sellaista sanakirjaa, jossa se on String. Joskus muulloin taas sellaista, jossa se onkin Bool, ja niin edelleen... Niinpä teemmekin sen tyypistä tyyppiparametrin t, jolloin saamme molemmat näistä, ja niin edelleen... data Puu t = Tyhja Solmu{ vasen :: Puu t, avain :: Int, 63

2 tieto :: t, oikea :: Puu t } deriving (Show) lisaa :: Int -> t -> Puu t -> Puu t lisaa x y Tyhja = Solmu{ vasen = Tyhja, avain = x, tieto = y, oikea = Tyhja } lisaa x y haara@(solmu{ avain=k }) x < k = haara{ vasen = lisaa x y $ vasen haara } x > k = haara{ oikea = lisaa x y $ oikea haara } otherwise = haara listasta :: [(Int,u)] -> Puu u listasta = foldr (uncurry lisaa) Tyhja listaksi :: Puu t -> [(Int,t)] listaksi = let listaksia Tyhja a = a listaksia haara a = listaksia (vasen haara) $ (avain haara,tieto haara) : listaksia (oikea haara) a in flip listaksia [] Nyt siis Puu String on tyyppi sellaisille puille, joissa tämä tietokenttä on merkkijonotyyppiä Puu Bool taas sellaisille, joissa se onkin totuusarvotyyppiä ja niin edelleen... Voi ajatella, että tyyppimuuttuja t korvataan vastaavalla tyypillä, eli että Puu String on data Puu String = Tyhja Solmu{ vasen :: Puu String, avain :: Int, tieto :: String, oikea :: Puu String } Puu Bool on data Puu Bool = Tyhja Solmu{ vasen :: Puu Bool, avain :: Int, tieto :: Bool, oikea :: Puu Bool } 64

3 Ertyisesti Tyhjan puun tyyppi on Tyhja :: Puu t jonka mukaan tämä vakioarvo on yhteinen kaikille kenttätyypeille t, mutta tyypinpäättelyssä Tyhja :: Puu String ja Tyhja :: Puu Bool ovat erillään. Tyypinpäättelynsä vuoksi Haskell osaa täydentää itse, millaista tyyppiä tämän tietokentän pitää milloinkin olla. Esimerkiksi listasta [(10,"kymmenen"),(100,"sata"),(1000,"tuhat")] tuottaa tuloksen, jonka tyyppi on Puu String, kun taas listasta [(10,True),(100,False),(1000,False)] tuottaakin tuloksen, jonka tyyppi onkin Puu Bool, ja niin edelleen... Nämä tyypit ovat erilliset. Haskell torjuu esimerkiksi yrityksen listasta [(10,True),(100,"sata"),(1000,False)] ilmoittaen ettei Bool ole sama tyyppi kuin String. Näitä tyyppimuuttujia käytetään myös funktioiden tyypityksissä. Esimerkiksi listasta :: [(Int,u)] -> Puu u ilmaisee, että 1. sen parametri on lista pareja, joissa ensimmäinen osa on Int (koska siitä tulee Solmuun avain) ja toinen osa on jotakin mielivaltaista tyyppiä u 2. arvo on sitten sellainen Puu jonka tietokentän tyyppinä on tämä sama u. Näin Haskellin tyypinpäättely löytää listasta sen käyttöyhteyden, jossa tämä ja sen, jossa se onkin ja niin edelleen... u = String u = Bool Myös esimerkiksi korkeamman kertaluvun yleiskäyttöiset listankäsittelyfunktiot ovat tällä samalla tavalla monimuotoisia. Vaikkapa tyypitys map :: (a -> b) -> [a] -> [b] 65

4 vaatii että syötelistan alkiotyypin a pitää olla sama kuin sovellettavan syötefunktion f parametrityypin takaa että silloin tämän funktion f tulostyyppi b on sama kuin tuloslistan alkiotyyppikin mutta muuten nämä tyypit a ja b saavatkin olla mitä tahansa. Tämä takaa funktion map monikäyttöisyyden: Se mukautuu mihin tahansa f, ja sen syöte- ja tuloslistojen alkiotyypit päätellään automaattisesti nyt käytetyn f mukaisiksi. Tämä automaattinen mukautuminen tekee parametrisesta monimuotoisuudesta ohjelmoijalle paljon vaivattomampaa kuin geneerisyydestä, jossa hänen täytyykin itse kirjoittaa arvot näille tyyppiparametreille. Kun jatkamme tätä hakupuuesimerkkiämme, niin törmäämme ongelmaan: Silloin kun hakupuussamme oli vain avainkenttä, niin riitti kirjoittaa Haskellfunktio tyyppiä puussa :: Int -> Puu -> Bool joka vain ilmoitti, onko tämä annettu avainarvo x tässa annetussa hakupuussa vaiko ei. (Sellaisen kirjoittaminen jätetään harjoitustehtäväksi.) Nyt kun hakupuussamme onkin myös avainta vastaava tietokenttä, niin vastaan Haskell-funktion katso :: Int -> Puu t ->? pitääkin palauttaa myös avainarvoa x vastaavan tietokentän sisältö, jos se on tässä hakupuussa. Mutta mikä olisi tämän funktion katso vastauksen tyyppi? Prelude tarjoaa juuri tähän käyttöön tyypin data Maybe a = Nothing Just a eli joko ei mitään tai just tällainen tulos. Siten voimme ottaa funktiomme tyypiksi katso :: Int -> Puu t -> Maybe t eli joko ei mitään (jos tätä avainta x ei ole tässä hakupuussa) tai just sitä vastaavan tietokentän arvo (joka on siis samaa tyyppiä t kuin hakupuussakin) (mutta itse funktion kirjoittaminen jätetään harjoitustehtäväksi). 66

5 Tämä on tyyppiturvallinen tapa ohjelmoida sellainen funktio, jonka muissa kielissä ohjelmoisi vaikkapa palauttamaan NULL-osoittimen, jos avainta x ei hakupuussa ole: Funktiota käytetään lausekkeessa case katso x puu of Nothing ->... Just k ->... jossa vastaavan tietokentän sisältö k näkyy vain siinä haarassa, jossa sellainen todellakin on olemassa. Parametrinen monimuotoisuus on siten tarkoitettu sellaisten funktioiden kirjoittamiseen, joiden toiminta ei riipu tyyppiparametriensa arvoista: Esimerkiksi listasta toimii aina samalla tavalla riippumatta tietokentän nykyisestä tyypistä se tekee aina syötelistastaan hakupuun. Alityyppimonimuotoisuus on taas tarkoitettu juuri sellaisten funktioiden kirjoittamiseen, joiden toiminta riippuu käsiteltävien alkioiden tyypeistä: Esimerkiksi Kuviolistan piirtäminen tapahtuu siten, että jokaista sen alkiota pyydetään piirtämään itsensä ja jokainen niistä osaa piirtää itsensä. Haskell osaa siis mainiosti parametrisen monimuotoisuuden. Voisiko sitä laajentaa joillakin piirteilla alityyppimonimuotoisuudesta? 5.2 Tyyppiluokat Laajennetaan hakupuuesimerkkiämme edelleen yrittämällä sallia myös sen avainkenttään sama monimuotoisuus, jonka sen tietokenttä jo sallii. Toisin sanoen tavoittelemme kaksiparametrista tyyppikonstruktoria Puu a t jonka tyyppiparametri a on sen avainkenttien, ja t on sen tietokenttien tyyppi. Tärmäämme ongelmaan: Tämä avainkenttien tyyppi a ei voikaan olla aivan mikä tahansa koska meidän täytyy olettaa, että sille on määritelty suuruusjärjestys eli operaattori (<) :: a -> a -> Bool koska funktio lisaa edellyttää sellaisen. 67

6 Siten meidän täytyy lisätä tyyppeihimme mahdollisuus rajoittaa monimuotoisuutta sanomalla mikä tahansa sellainen tyyppi a, jolle on määritelty seuraavat funktiot.... Tai jos vaihdamme näkökulman tyypeistä funktioihin, mahdollisuus kuormittaa (overload) yksi ja sama funktion nimi kuten (<) monelle eri tyypille a. Tämä kuormitusnäkökulma lähestyy olio-ohjelmointia: Jokainen tyyppi a tietää itse miten sen tyyppisiä arvoja vertaillaan toisiinsa. Toisin sanoen, jokaisella tyypillä a on oma funktionsa nimeltään (<), jota sen tyyppisten avainten lisaamisessa käytetään. Olio-ohjelmoinnin tapaan myös Haskellissa kutsutaan metodeiksi niitä funktioiita, jotka voidaan kuormittaa eri tyypeille a. Miten siis lisätään tämä mahdollisuus siten, että tyypinpäättelykin yhä toimii? Haskellin ratkaisu ovat tyyppiluokat (type classes): Tyyppiluokka on kokoelma sellaisia tyyppejä, jotka kaikki toteuttavat jonkin tietyn rajapinnan. Esimerkiksi tyyppiluokka Ord eli järjestetyt (Ordered) tyypit koostuu niistä tyypeistä t jotka toteuttavat sellaisen rajapinnan, johon kuuluu funktio (<) :: t -> t -> Bool eli joilla on järjestys. Tyyppi t voi liittyä tyyppiluokan instanssiksi eli jäseneksi määrittelemällä, miten se toteuttaa kyseisen rajapinnan. Tyyppi t voi määritellä sen itse kuten (ohjelmoija) haluaa, joten tyyppiluokan rajapinnan funktiot ovat kuormitettuja. Sitten tyyppejä kirjoittaessa voidaan ilmoittaa, että nyt pitääkin rajoittua vain tiettyjen tyyppiluokkien instansseihin. Esimerkiksi Data.List.sort :: (Ord a) => [a] -> [a] tarkoittaa, että syötelista voidaan järjestää ( sortata ) jos sen alkiotyypillä a on järjestys mutta muuten a voi olla millainen tyyppi tahansa. Tällaiset rajoitteet tyyppimuuttujille kirjoitetaan siis (Rajoite 1,Rajoite 2,Rajoite 3,...,Rajoite k ) =>... jossa jokainen Rajoite i on TyyppiLuokanNimi tyyppimuuttuja 68

7 ja se tarkoittaa, että tämän tyyppimuuttuja n arvot pitää valita tästä tyyppiluokasta. Tämä merkintä => on valittu muistuttamaan logiikan implikaationuolta : Jos nämä rajoitteet ovat voimassa niin sitten... Ne voidaan sijoittaa Haskell-ohjelmassa eri paikkoihin: datatyypissä se voidaan kirjoittaa heti datan jälkeen eli data (...) => Nimi... ja silloin se tarkoittaa, että koko tämännimi nen tyyppi on olemassa vain, jos nämä rajoitteet ovat voimassa. Tämä vaatimus on globaali: Se koskee myös kaikkia niitä funktioita, joissa tämännimistä tyyppiä käytetään. funktion tyypissä se voidaan kirjoittaa heti merkinnän :: jälkeen eli nimi :: (...) =>... ja silloin se tarkoittaa, että tämännimi stä funktiota ei voi käyttää, elleivät nämä rajoitteet ole voimassa. Se on siis lokaali ehto. Tyyppiluokan määrittelyn sisäpuolella esitellyt funktiot ovat siis niitä metodeja, jotka voidaan ja pitääkin kuormittaa ulkopuolella eli tavallisessa Haskell-ohjelmakoodissa esitellyt funktiot voivat kutsua näitä metodeja nimellä, ja silloin Haskell valitsee tyypinpäättelynsä perusteella sen version, jota nyt pitää käyttää. Esimerkiksi Haskell päättelee, että kutsussa Data.List.sort ["hei","vaan","kaikki","ohjelmoijat"] pitää käyttää merkkijonojen vertailua (<) :: String -> String -> Bool kun taas kutsussa Data.List.sort "hei vaan kaikki ohjelmoijat" pitääkin käyttää yksittäisten merkkien vertailua (<) :: Char -> Char -> Bool mutta molemmissa käytetään samaa sort-algoritmia. 69

8 Javan rajapinnat eli interfacet muistuttavat näitä Haskellin tyyppiluokkia mutta siis ilman tyypinpäättelyä. Tyyppiluokat ovat yksi Haskellin mukanaan tuomista uutuuksista ohjelmointikielten tyyppijärjestelmiin. Niitä pidetäänkin hyvänä ratkaisuna ylikuormittamiseen silloin kun ohjelmointikielessä on tyypinpäättely mutta ei ole alityypin käsitettä. Lisäksi Haskellissa on sellaisia sääntöjä kuin jos tyyppi t kuuluu tyyppiluokkaan Ord niin myös tyyppi [t] kuuluu tyyppiluokkaan Ord koska... Esimerkiksi merkkijonojen aakkosjärjestys onkin saatu merkkien aakkosjärjestyksestä tällaisella säännöllä. Tällaiset säännöt ovat jo valmiina niille tyypeille, jotka Haskell tarjoaa. Ohjelmoija voi myös lisätä sellaisia sääntöjä omille tyypeilleen, ja Haskellin tyypinpäättely osaa huomioida myös ne. Haskellissa tyyppi voi kuulua tyyppiluokkaan eli toteuttaa sen rajapinnan vain yhdellä tavalla. Esimerkiksi tyyppiluokan Ord metodi (<) tarkoittaa tämän tyypin kanonista eli sitä ainoaa luonnollista järjestystä. Siten esimerkiksi tyypin String tämä oikea järjestys on edellisen säännön nojalla merkkien oikeaan järjestykseen perustuva sanakirjajärjestys. Siinä siis suuret ja pienet kirjaimet erotellaan toisistaan. Joskus ohjelmoija haluaisikin sellaisen järjestyksen, jossa niitä ei eroteltaisikaan toisistaan eli liittääkin Stringit tällä toisella tavalla tyyppiluokkaan Ord. Haskell-ohjelmointifilosofiassa sellaiset merkkijonot ovat kuitenkin uusi eri tyyppi kuin String koska niiden ominaisuudet poikkeavat toisistaan. Tällaisessa tilanteessa on luontevaa määritellä se newtype MunString = SunStringista { sunstringiksi :: String } jonka jälkeen ohjelmoija voi sitten määritellä itse miten tämä hänen oma MunStringinsa on tyyppiluokan Ord instanssi. Jatketaan sitten sanakirjaesimerkkiämmme, mutta palataan takaisin nimettömiin kenttiin. Tehdään nyt myös sen avainkentästä, joka ennen oli tyyppiä Int, polymorfinen tyyppiä k. Koska avainarvoja pitää vertailla funktiossa lisaa, niin meidän täytyy asettaa sille rajoite (Ord k) =>... Nyt voisi olla luontevaa asettaa se koko datatyyppimäärittelyyn, koska voitaisiin luontevasti ajatella, ettei koko tyyppiä hakupuu k t olekaan olemassa ellei sen avaintyyppi k ole järjestetty. Asetetaan se kuitenkin sen sijaan funktioittain nähdäksemme, mihin se tarvitaan ja missä pärjätään ilman sitä. 70

9 Se tarvitaan siis ainakin funktioon lisaa......sekä myös funktioon listasta koska se kutsuu sitä. Mutta se tarvitaan vain niihin, koska Puun muuntamiseen listaksi ei tarvita avainten järjestystä. data Puu k t = Tyhja Solmu (Puu k t) k t (Puu k t) deriving (Show) lisaa :: (Ord k) => k -> t -> Puu k t -> Puu k t lisaa x y Tyhja = Solmu Tyhja x y Tyhja lisaa x y haara@(solmu vasen avain tieto oikea) x < avain = Solmu (lisaa x y vasen) avain tieto oikea x > avain = Solmu vasen avain tieto (lisaa x y oikea) otherwise = haara listasta :: (Ord k) => [(k,t)] -> Puu k t listasta = foldr (uncurry lisaa) Tyhja listaksi :: Puu k t -> [(k,t)] listaksi = let listaksia Tyhja a = a listaksia (Solmu vasen avain tieto oikea) a = listaksia vasen $ (avain,tieto) : listaksia oikea a in flip listaksia [] Nyt siis Haskell päättelee esimerkiksi seuraavat tyypit: *Main> listasta [("hei",12),("taas",5.5)] Solmu (Solmu Tyhja "hei" 12.0 Tyhja) "taas" 5.5 Tyhja it :: Puu [Char] Double *Main> listasta [((1,3),True),((2,7),False)] Solmu (Solmu Tyhja (1,3) True Tyhja) (2,7) False Tyhja it :: Puu (Integer, Integer) Bool Siten Haskell todellakin osaa päätellä nyt myös avaintyypin k kuten tavoittelimmekin. Haskell on jopa niin nokkela, että se osaa päätellä tyypin(integer,integer) olevan järjestetty eli kelpaavan avaimeksi! Sen Haskell tekee säännöllään Jos Ord a ja Ord b niin myös Ord (a,b). Näin ohjelmoijan on varsin vaivatonta ottaa käyttöön sellaisiakin hakupuutyyppejä, joiden avaintyyppi on monimutkainen koska hänen ei tarvitse itse kirjoittaa niiden tyyppejä eikä määritellä niiden arvojen keskinäistä järjestystä mutta hän voi silti tehdä niinkin, jos haluaa. 71

10 5.2.1 Johdetut instanssit Olemme tähän saakka kirjoittaneet data- ja newtype-määrittelyjemme loppuun...deriving (Show) selvittämättä mitä se oikein tarkoittaa. Se tarkoittaa intuitiivisesti että liitä tämä minun uusi tyyppini tyyppiluokan Show instanssiksi siihen tavalliseen tapaan. Hyvin tavallinen tyyppimäärittelyn lopetus on esimerkiksi deriving (Eq,Ord,Show) joka intuitiivisesti tarkoittaa, että salli tämän tyypin arvoille tavalliset yhtäsuuruusvertailut (==), järjestysvertailut (<) ja näyttämisen (show) käyttäjälle. Se siis säästää ohjelmoijalta sen tavallisen tavan kirjoittamisen mutta sekin on sallittua, eli tämän deriving-automatiikan voi myös ohittaa, jos haluaakin tehdä jotakin muuta kuin sen tavallisen tavan. Tutustutaan seuraavaksi sellaisiin keskeisiin tyyppiluokkiin, joille Haskell tarjoaa tämän deriving-automatiikan, eli joille se osaa tarvittaessa johtaa instanssit automaattisesti. Yhtäsuuruus Tyyppiluokka Eq tarkoittaa niitä tyyppejä, joille on määritelty yhtäsuuruusvertailu (==). Silloin niille on automaattisesti määritelty myös sen vastakohta eli erisuuruusvertailu (/=). Yhtäsuuruusvertailun voi johtaa automaattisesti valtaosalle Haskellin tyypeistä. Poikkeuksena ovat vain funktiotyypit ja I/O-operaatioiden tyyppi (johon palaamme myöhemmin) sekä kaikki tyypit joiden osina ne esiintyvät. (Esimerkiksi funktioiden yhtäsuuruusvertailuhan tiedettiin ratkeamattomaksi ongelmaksi Ricen lauseen nojalla.) Jos ohjelmoija haluaakin määritellä tyypilleen yhtäsuuruusvertailun itse, niin hänen riittää kuormittaa sille toinen näistä operaattoreista (==) ja (/=). Järjestys Olemme jo hakupuuesimerkissämme kohdanneet tyyppiluokan Ord eli ne tyypit, joilla on järjestysrelaatio (<). Myös järjestysrelaation voi johtaa automaattisesti valtaosalle Haskellin tyypeistä. Poikkeuksena ovat vain funktiotyypit sekä I/O-operaatioiden ja I/O-virheiden tyypit sekä kaikki tyypit joiden osina ne esiintyvät. Tämä automaattisesti johdettu järjestys vertailee tyypin arvoja seuraavasti: 1. Jos niillä on eri konstruktorit, niin sitten se arvo on pienempi, jonka konstruktori esiintyy ensin data-määrittelyssä 72

11 2. Jos niiden konstruktorit ovat samat, niin sitten aletaan vertailla niiden kenttiä siinä järjestyksessä kuin ne esiintyvät data-määrittelyssä. Jos ohjelmoija haluaakin määritellä omalle tyypilleen a järjestyksen itse, niin silloin hän varmistaa, että tämä tyyppi a on myös tyyppiluokan Eq instanssi. Tyyppi ei voi olla järjestetty ellei sillä ole yhtäsuuruutta, eli kyseessä on totaali järjestysrelaatio. kuormittaa tyypilleen operaattorin (<=) eli pienempi tai yhtasuuri kuin. Muut operaatiot (<), (>), (>=), max, min ja compare tulevat määritellyiksi automaattisesti sen pohjalta. Tai vaihtoehtoisesti hän voi määritellä tyypilleen tämän metodin, jonka tyyppi on data Ordering = LT EQ GT deriving (Eq, Ord, Enum, Read, Show, Bounded) compare :: (Ord a) => a -> a -> Ordering eli Less Than, EQual to tai Greater Than. Tulostaminen merkkijonoksi Tyyppiluokka Show on ne tyypit t, joiden arvot voi tulostaa merkkijonoksi. Kun juuri laskettu arvo kuuluu tällaiseen luokkaan, niin silloin Haskell-tulkkimme ghci näyttää sitä vastaavan merkkijonotulosteen. Muuten ghci ilmoittaakin, että se kyllä sai laskettua pyydetyn arvon, muttei tiedä kuinka sen näyttäisi käyttäjälleen. Tämä keskeisin tulosta merkkijonoksi -funktio on nimeltään show. (Tyyppiluokkaan Show kuuluu muitakin sen sukuisia funktioita.) Sen automaattisesti johdettu muoto tulostaa arvon samaan tapaan kuin sen voisi kirjoittaa Haskell-lausekkeenakin. Merkkijonosta lukeminen Tyyppiluokan Show vastaluokka on Read eli ne tyypit t, joiden arvot voi lukea merkkijonosta. Funktion show vastineena on lue merkkijonosta -funktio nimeltään read. (Tyyppiluokkaan Read kuuluu muitakin sen sukuisia funktioita.) Jos tyyppi t kuuluu tyyppiluokkiin Eq, Show ja Read, niin silloin on syytä vaatia, että sen jokaiselle arvolle x pätee read $ show x == x 73

12 eli että jos arvo tulostetaan ensin merkkijonoksi ja sitten se luetaan takaisin arvoksi, niin saadaan takaisin juuri sama arvo. Jos tämä luku-kirjoitus-muuttumattomuus (read-write invariance) ei pädekään, niin silloin ohjelman I/O ei olekaan aivan uskollinen viittausten läpinäkyvyydelle. Se pätee automaattisesti johdetuille funktioille read ja show. Usein funktiota read käytettäessä tarvitaan jokin ohjelmoijan kirjoittama tyyppiinformaatio kertomaan, minkä tyyppiseksi arvoksi tämä merkkijono on tarkoitus tulkita. Miten Haskell muuten tietäisi esimerkiksi lausekkeesta read "123" onko nyt tarkoitus lukea luku 123 Inttinä, Integerinä, Floatina vai Doublena? Siis esimerkiksi funktio muunna annettu merkkijono matemaattisen kokonaisluvun ja pitkän liukuluvun pariksi voidaan kirjoittaa vaikkapa pariksi :: String -> (Integer,Double) pariksi = read jossa sen tyyppi ja tyypinpäättely pitävät huolen siitä, että tässä tämä readin versio lukee mitä sen pitääkin. Tämän tyyppiluokan funktiot ovat melko yksinkertaisia, joten syötteiden monimutkaistuessa ohjelmoijan on usein syytä kirjoittaa itse parempi jäsennin (parser). Luetellut tyypit Tyyppi on lueteltu (enumeration) jos sen yhdelläkään konstruktorilla ei ole yhtään kenttää. Esimerkiksi Bool, Ordering ja Char ovat lueteltuja. Samoin kokonaislukutyypit ajatellaan luetelluiksi, koska niilläkin voitaisiin ajatella olevan data-määrittely konstruktorittomin kentin kuten data Integer = vaikka sellaista ei tietenkään todellisuudessa voida kirjoittaa. Sellaiselle voi sanoa... deriving (Enum,...) joka liittää sen lueteltujen tyyppien tyyppiluokkaan. 74

13 Tällaisella luetellulla tyypillä on luontevasti funktiot successor eli seuraava arvo sekä sen vastinpari predecessor eli edellinen arvo. Liukuluvutkin ajatellaan luetelluiksi tyypeiksi ottamalla näiksi funktioksi (± 1.0). Jos tyyppi t kuuluu tyyppiluokkaan Enum, niin silloin vastaavassa listatyypissä [t] voidaan käyttää luvun 3.2 lukusarjanotaatiosta tuttua merkintää... Siten esimerkiksi seuraava tulee mahdolliseksi: data Viikonpaivat = Ma Ti Ke To Pe La Su deriving (Enum,Eq,Ord,Show,Bounded) arki = [Ma.. Pe] jokatoinen = cycle $ [Ma,Ke..] ++ [Ti,To..] Ala- ja ylärajat Tyyppiluokka Bounded on ne tyypit, joilla on ala- ja ylärajat, eli pienin arvo nimeltään minbound suurin arvo nimeltään maxbound. Siis esimerkiksi Int kuuluu tähän luokkaan, ja siten minbound :: Int on pienin ja maxbound :: Int suurin ohjelmoijan kokonaisluku. Jokaisella äärellisellä luetellulla tyypillä joko jo on nämä ala- ja ylärajat tai ne voidaan määritellä sille deriving-automatiikalla. Automatiikka ottaa silloin alarajaksi ensimmäisen ja ylärajaksi viimeisen konstruktorin. Automatiikka soveltuu myös jokaiseen sellaiseen tyyppiin, jolla on vain yksi konstruktori jonka jokaisella kentällä on ala- ja ylärajat. Erityisesti k-kenttäinen monikko on tällainen tyyppi, joten esimerkiksi *Main> minbound :: (Viikonpaivat,Char) (Ma, \NUL ) it :: (Viikonpaivat, Char) Sivuhuomautus: Jos joskus täytyy kirjoittaa tämä k-kenttäisen monikon ainoa konstruktori, niin se on (,,,...,) :: τ }{{} 1 -> τ 2 -> -> τ k -> (τ 1,τ 2,...,τ k ). k 1 kpl. 75

14 5.2.2 Lukutyyppiluokat Tutustutaan seuraavaksi joihinkin Haskellin lukutyyppiluokkiin. Jotkut niistä vastaavat jotakin algebrallisten rakenteiden kokoelmaa. Perusluokka Num eli luvut yleensä vastaa algebrallista rakennetta nimeltään rengas (ring). Siellä on määritelty seuraavat operaatiot: yhteenlasku (+) vähennyslasku (-) etumerkin käsittely eli luvun itseisarvo (abs), pelkän etumerkin otto (signum) ja etumerkin vaihto (negate) vakio frominteger joka muuntaa annetun pitkän kokonaislukuvakion tämän tyyppiseksi vakioksi. Sen avulla Haskell-koodissa esiintyvät kokonaislukuvakiot tulkitaan automaattisesti halutun lukutyypin vakioarvoksi. Perusluokka Integral eli kokonaisluvut jakolaskulla vastaa algebrallista rakennetta nimeltään Euklidinen (Euclidean) rengas. Siinä luokkaan Num lisätään myös sellainen jakolasku, josta jää tätä samaa tyyppiä oleva osamäärä ja jakojäännös. Siis sellaiset funktiot kuin quot, rem,... Perusluokka Fractional eli luvut yleensä jakolaskulla vastaa algebrallista rakennetta nimeltään kunta (field). Siinä luokkaan Num lisätäänkin sellainen jakolasku (/), jonka tuloskin on tätä samaa tyyppiä. Siten kokonaislukutyypit eivät kuulukaan tähän luokkaan, mutta liuku- ja murtolukutyypit kuuluvat. Liukulukutyyppien erilaisia funktioita on ryhmitelty seuraaviin tyyppiluokkiin: Floating sisältää trigonometrisia yms. funktioita kuten sin RealFrac sisältää muunnokset kokonaislukuihin kuten floor yms. RealFloat sisältää liukulukujen fyysiseen esitykseen liittyviä funktioita kuten kuinka monen bitin laskentatarkkuutta ne käyttävät yms. Haskell-kieli tarjoaa siis myös murtoluvut, mutta ne eivät ole heti käyttövalmis osa itse kieltä, vaan ohjelmoijan pitää ottaa ne käyttöön kirjoittamalla lähdekoodinsa alkuun import Data.Ratio jonka jälkeen hänellä on käytössään tyyppi Rational eli matemaatikon mielivaltaisen tarkkuuden murtoluvut, joiden osoittaja ja nimittäjä ovat tyyppiä Integer 76

15 tyyppikonstruktori Ratio jolla hän voi käyttää sen sijasta omia pienemmän tarkkuuden mutta nopeampia murtolukutyyppejään. Esimerkiksi tyyppi Ratio Int on sellaiset murtoluvut, joiden osoittaja ja nimittäjä ovatkin tyyppiä Int. Sen jälkeen hän voi laskea myös niillä. Vastaavalla tavalla voi ottaa käyttöön kompleksiluvut kirjastosta Data.Complex Instanssin määrittely Kun ohjelmoija haluaa liittää itse määrittelemänsä tyypin t tyyppiluokkaan C joka ei tue deriving-automatiikkaa, tai tukisi, mutta ohjelmoija haluaakin liittää tyyppinsä t tyyppiluokkaan C jollakin muulla kuin automatiikan tarjoamalla tavalla niin hän kirjoittaa instanssin määrittelyn muotoa instance C t where. jonka sisällä hän kuormittaa tämän tyyppiluokan C funktiot tälle omalle tyypilleen t. Otetaan ensimmäiseksi esimerkiksemme tilanne, jossa ohjelmoija tarvitsee sellaiset matemaattiset kokonaisluvut, joissa on myös negatiivinen ja positiivinen äärettömyys. Ensiksi ohjelmoija määrittelee oman tyyppinsä InfInteger jonka arvot ovat Hän saa deriving-automatiikasta niiden,..., 2, 1, 0, +1, +2,..., +. }{{} tyypin Integer arvot yhtäsuuruuden Eq koska hänelle kelpaa se tavallinen yhtäsuuruus kuten valtaosassa ohjelmointitilanteista järjestyksen Ord kunhan hän kirjoittaa konstruktorinsakin haluttuun järjestykseen. Toisaalta hän haluaakin tulostaa äärettömyyksiinsä ± etumerkit, joten hän ei käytäkään automatiikkaa tyyppiluokalle Show vaan kirjoittaakin sen instanssin itse. Tämän instanssinsa sisällä hän sitten kuormittaa sen metodin show tälle omalle tyypilleen InfInteger haluamallaan tavalla. Tulkki ghci käyttää tätä tulostusasua sen arvoille. data InfInteger = NegInf Fin Integer PosInf 77

16 deriving (Eq,Ord) instance Show InfInteger where show NegInf = "-Infinite" show PosInf = "+Infinite" show (Fin n) = "Finite " ++ show n instance Bounded InfInteger where minbound = NegInf maxbound = PosInf instance Num InfInteger where -- kokonaislukuvakiosta frominteger = Fin -- yhteenlasku (Fin x) + (Fin y) = Fin (x + y) (Fin _) + y = y x + (Fin _) = x NegInf + NegInf = NegInf PosInf + PosInf = PosInf -- vastaluku negate NegInf = PosInf negate (Fin x) = Fin (negate x) negate PosInf = NegInf -- itseisarvo abs NegInf = PosInf abs (Fin x) = Fin (abs x) abs PosInf = PosInf -- etumerkki signum NegInf = -1 signum (Fin x) = Fin (signum x) signum PosInf = 1 -- kertolasku (Fin 0) * _ = 0 (Fin x) * (Fin y) = Fin (x * y) (Fin x) * y x>0 = y otherwise = negate y NegInf * NegInf = PosInf NegInf * PosInf = NegInf PosInf * NegInf = NegInf PosInf * PosInf = PosInf x * y = y * x Tyypillä InfInteger on myös luontevat ala- ja ylärajat, joten ohjelmoija voi ilmaista myös ne. Tyyppiä InfInteger ei kuitenkaan voi pitää lueteltuna: Minkä arvon antaisit esimerkiksi lausekkeelle succ NegInf eli arvoa seuraava suurempi arvo? 78

17 Ohjelmoija haluaa myös laskeakin tämän tyyppisillä luvuillaan, joten hän liittää tämän tyyppinsä InfInteger myös luokkaan Num. Haskell-standardin mukaan ohjelmoijan täytyy kuormittaa sen metodeista kaikki muut paitsi joko vähennyslaskua tai etumerkin vaihtoa niistä toisen Haskell osaa kuormittaa itsekin kunhan toinen on kuormitettu. Erityisesti frominteger-kuormitus mahdollistaa InfInteger-tyyppisten kokonaislukuvakioiden käytön. Tosin vähennyslaskun tulosta ei voi määritellä, koska sitä varten pitäisi tietää, kumpi näistä äärettömyyksistä on suurempi ja paljonko suurempi. Siinä tilanteessa Haskell keskeyttää laskennan suoritusaikaiseen virheeseen muuta ei liene tehtävissä. Otetaan toisena esimerkkinämme tyyppikonstruktori, jotta nähdään sen tyyppiparametrien käsittelyä. Käytetään jälleen hakupuutamme (ilman kentännimiä) jossa sekä avain- että tietokenttä on monimuotoinen. Kaksi sanakirjaa ovat samat, jos ne sisältävät täsmälleen samat (avain,tieto)- parit. Jos hakupuuta ajatellaan sanakirjana, niin silloin kaksi hakupuuta ovat siis samat, jos kummassakin on täsmälleen samat(avain,tieto)-parit riippumatta siitä, minkä muotoisia nämä puut ovat. Jos käytettäisiin hakupuulle automatiikkaa deriving (Eq) niin saataisiin(==) joka ottaisi huomioon puiden muodon. Määritellään siis sen sijaan hakupuulle käsin sellainen tyyppiluokan Eq-instanssi, joka vertaileekin vain niiden (avain,tieto)-pareja. Ensimmäinen versiomme alkaa siten instance Eq (Puu k t) where jonka voi lukea että tyyppi Puu k t kuuluu tyyppiluokkaan Eq siten, että... Nyt kuitenkin törmäämme ongelmaan: Jotta voisimme määritellä instanssin sisällä sen haluamamme operaattorin (==) :: Puu k t -> Puu k t -> Bool me tarvitsemme sitä varten vastaavat operaattorit (==) :: k -> k -> Bool (==) :: t -> t -> Bool myös sen avainkentän tyypille k ja tietokentän tyypille t. Toisin sanoen, myös sen avainkentän tyypin k ja tietokentän tyypin t pitää kuulua tyyppiluokkaan Eq. 79

18 Kun lausumme nämä rajoitteet julki, niin saamme lopullisen versiomme alkamaan instance (Eq k,eq t) => Eq (Puu k t) where jonka voi lukea että jos tyyppi k kuuluu tyyppiluokkaan Eq ja tyyppi t kuuluu tyyppiluokkaan Eq niin siinä tapauksessa myös tyyppi Eq Puu k t kuuluu tyyppiluokkaan Eq siten, että... Nyt pääsemme kirjoittamaan tämän instanssimme sisältöä eli tuota siten, että... -osaa eli ohjelmoimaan haluamaamme operaattoria (==) :: Puu k t -> Puu k t -> Bool data Puu k t = Tyhja Solmu (Puu k t) k t (Puu k t) deriving (Show) lisaa :: (Ord k) => k -> t -> Puu k t -> Puu k t lisaa x y Tyhja = Solmu Tyhja x y Tyhja lisaa x y haara@(solmu vasen avain tieto oikea) x < avain = Solmu (lisaa x y vasen) avain tieto oikea x > avain = Solmu vasen avain tieto (lisaa x y oikea) otherwise = haara listasta :: (Ord k) => [(k,t)] -> Puu k t listasta = foldr (uncurry lisaa) Tyhja listaksi :: Puu k t -> [(k,t)] listaksi = let listaksia Tyhja a = a listaksia (Solmu vasen avain tieto oikea) a = listaksia vasen $ (avain,tieto) : listaksia oikea a in flip listaksia [] instance (Eq k,eq t) => Eq (Puu k t) where p == q = listaksi p == listaksi q Itse ohjelmointi taas on suoraviivaista: 1. Ensin muunnetaan kumpikin syötepuu p ja q listaksi (avain,tieto)-pareja. Tämä muunnos listaksi ohjelmoitiin siten, että nämä parit ovat järjestyksessä avain tensa suhteen. Koska kyseessä on sanakirja, niin yhtä avain ta kohden on vain yksi tieto. 2. Sitten riittää verrata näitä (avain,tieto)-parien listoja toisiinsa niiden operaattorilla 80

19 (==) :: [(k,t)] -> [(k,t)] -> Bool jonka olemassaolon varmistamiseksi me itse asiassa tarvitsimme sen rajoitteen että tyyppi k kuuluu tyyppiluokkaan Eq ja tyyppi t kuuluu tyyppiluokkaan Eq. Haskellin tyypinpäättely osaa nyt tuottaa tämän listavertailuoperaattorin: Haskell tuntee säännön jos alkiotyyppi u kuuluu tyyppiluokkaan Eq niin myös listatyyppi [u] kuuluu luokkaan Eq siten, että.... Haskell tuntee myös säännön jos tyyppi v kuuluu tyyppiluokkaan Eq ja tyyppi w kuuluu tyyppiluokkaan Eq niin myös tyyppi (v,w) kuuluu tyyppiluokkaan Eq siten, että.... Sitten Haskell yhdistelee nämä siten, että... -osat sopivasti. Itse asiassa me kirjoitimme itsekin juuri yhden tällaisen säännön lisää: Oman instanssimme joka alkoi instance (Eq k,eq t) => Eq (Puu k t) where ja jonka sisältö antoi sen siten, että... -osan. Tällaisen säännön voi tulkita eräänlaisena perintänä : Koko hakupuutyyppimme perii oman yhtäsuuruutensa (==) kenttiensä yhtäsuuruuksista. Näillä instanssimäärittelyillä voi lisätä uusia tyyppejä tyyppiluokkiin. Mutta niillä ei voi muuttaa jo aikaisemmin määriteltyjä instansseja muutenhan niillä voisi muuttaa kaikessa hiljaisuudessa jo kertaalleen kirjoitettua ja testattua ohjelmakoodia koskematta sihen Oman tyyppiluokan määrittely Siirrytään sitten kokonaan oman tyyppiluokan määrittelyyn. Sen syntaksi on class TyyppiLuokanNimi tyyppiparametri where. jonka sisällä esitellään sen jokaisen kuormitettavan metodin nimi ja tyyppi voi määritellä sen metodeille oletustoteutuksia. Tällaista oletustoteutusta käytetään silloin, jos instanssimäärittely ei annakaan sille omaa toteutustaan. Lisäksi heti varatun sanan class jälkeen jälleen olla rajoiteosa jossa voi ilmaista, mitä tältä tyyppiparametrilta pitää olettaa. Tässä luokkamäärittelyssä 81

20 TyyppiLuokanNimi on nyt määriteltävän luokan nimi tyyppiparametri edustaa sitä tyyppiä, jonka nyt on tarkoitus kuulua tähän luokkaan eli sen voi lukea että tyyppiparametri n arvo t kuuluu tyyppiluokkaan nimeltä TyyppiLuokanNimi silloin, kun tälle tyypille t on määritelty metodit nimeltä... Otetaan esimerkiksemme määritella kokonaislukujen neliöjuurifunktio: Sovitaan, että kokonaisluvun n neliöjuuri isqrt n on suurin sellainen kokonaisluku m jolla m 2 n. Siis matemaattisesti m = n (7) jota ei kuitenkaan voi aina käyttää ohjelmoinnissa: Entä jos n onkin niin iso Integer ettei Doublen neliöjuurifunktion sqrt laskentatarkkuus enää riitäkään? Asetetaan siis tavoitteeksemme määritellä sellainen kuormitettu funktio isqrt :: t -> t jossa käytetään yhtälöä (7) niille tyypeille t joilla ei ole vielä pyöristysvirheen riskiä. Sen sijaan tämä isqrt toteutetaankin hitaampana binäärihakuna sellaiselle tyypeille t jolla tiedetään olevan pyöristysvirheen riski, tai josta tiedetään vain, että se on jonkinlainen kokonaislukutyyppi. Lisäksi ohjelmoijalle halutaan tarjota mahdollisuus saada hänen itsensä määrittelemille uusille kokonaislukutyypeille automaattisesti ainakin tämä binäärihakumenetelmä, sekä manuaalisesti käyttöön yhtälön (7) sitä nopeampi menetelmä. Tätä varten määritellään uusi oma tyyppiluokka Isqrt jossa on rajoite että siihen kuuluvan tyypin pitää kuulua myös tyyppiluokkaan kokonaisluvut eli Integral ainoa metodi on tämä isqrt sille annetaan oletusmäärittely binäärihakuna. Sitä käytetään, ellei ohjelmoija erikseen sano että käytä tälle tyypille yhtälöä (7). Lisäksi kirjoitetaan yhtälö (7) funktiona hwsqrt. Se jätetään tämän tyyppiluokan Isqrt ulkopuolelle, koska sitä itseään ei ole tarpeen kuormittaa: Yhtälö (7) ei riipu kokonaisluvun n tyypistä. 82

21 Se kuitenkin määritellään monimuotoiseksi: Siinä käytetty operaatio muunna n Doubleksi riippuu kokonaisluvun n tyypistä funktio fromintegral on kuormitettu. Matemaatikon kokonaisluvuille Integer käytetään tätä oletusmäärittelyä, koska niissä on varmasti ylivuodon riski. Silloin voimme jättää where-osan pois. {- Kokonaisluvun n neliöjuuri on suurin kokonaisluku m jolla m^2<=n. -} import Data.Int import Data.Word import Data.Bits {- Perusratkaisu on käyttää binäärihakua. -} class (Integral t) => Isqrt t where isqrt :: t -> t isqrt 0 = 0 isqrt 1 = 1 isqrt n n > 1 = {- binäärihaun invariantti: p^2 < n < q^2 -} let bsearch p q = if q-p>1 then let m = (p+q) div 2 in case (m^2) compare n of LT -> bsearch m q EQ -> m GT -> bsearch p m else p in bsearch 0 n {- Laitetason neliöjuuri IEEE-liukulukuaritmetiikalla. -} hwsqrt :: (Integral t) => t -> t hwsqrt = floor. (sqrt :: Double -> Double). fromintegral {- Matemaatikon kokonaisluvuille oletusmenetelmällä. -} instance Isqrt Integer {- Laskeeko laitetaso oikein tämän luvun neliöjuuren? -} hwisok :: (Integral t) => t -> Bool hwisok n = 83

22 let m :: Integer m = isqrt $ fromintegral n in m == fromintegral (hwsqrt n) {- Jos hwisok (maxbound::t) niin silloin tyypille t sallitaan laitetason käyttö. -} instance Isqrt Int8 where isqrt = hwsqrt instance Isqrt Int16 where isqrt = hwsqrt instance Isqrt Int32 where isqrt = hwsqrt instance Isqrt Int64 where isqrt = hwsqrt instance Isqrt Int where isqrt = hwsqrt instance Isqrt Word8 where isqrt = hwsqrt instance Isqrt Word16 where isqrt = hwsqrt instance Isqrt Word32 where isqrt = hwsqrt instance Isqrt Word64 where isqrt = sqrt64 instance Isqrt Word where isqrt = if bitsize (undefined::word) < 64 then hwsqrt else sqrt64 {- Etumerkittömän 64-bittisen luvun viimeinen 1k aiheuttaisi pyöristysvirheen laitetasolla. -} sqrt64 :: (Bounded t,integral t) => t -> t sqrt64 n = hwsqrt $ min n $ maxbound Apufunktio hwisok ilmoittaa, onnistuiko hwsqrt laskemaan syötelukunsa neliöjuuren ilman pyöristysvirhettä. Tämä selviää vertaamalla sen tulosta Integerilla laskettuun virheettömään tulokseen m. Silloin kutsu hwisok (maxbound :: t) ilmoittaa, riittääkö hwsqrt-tarkkuus tälle tyypille t... tällä ghci-toteutuksella! Jos se vastaa True niin silloin voimme kirjoittaa vastaavan instance Isqrt t where isqrt = hwsqrt 84

23 ottamaan sen käyttöön. Vakiokirjastossa Data.Int määritellään useita kokonaislukutyyppejä niiden bittimäärän mukaan: Tyyppi Intb on b-bittiset etumerkilliset kokonaisluvut jossa tämä bittimäärä b = 8, 16, 32, 64. Tässä siis tuo b on osa tyypin nimeä tekstinä, eli tyyppi nimeltään Word16 on 16-bittiset kokonaisluvut jne. Myös kaikille niillekin hwisok-testi sallii hwsqrt-funktion käytön. Vastaavasti vakiokirjastossa Data.Word määritellään useita etumerkittömiä kokonaislukutyyppejä: Wordb samoille bittimäärille b = 8, 16, 32, 64. Word toteutuksen luonnolliselle bittimäärälle. Samoin kuin Int on toteutuksen luonnollinen etumerkillinen kokonaislukutyyppi. Luennoijan kannettavassa nämä molemmat luonnolliset tyypit ovat 64- bittisiä. Opetussaleissa tämä luonnonvakio taas vaikuttaa olevan 32 bittiä... Kun lähestytään etumerkittömien 64-bittisten kokonaislukujen eli tyypin Word64 (ja luennoijan koneessa siis myös tyypin Word) laskentatarkkuuden ylärajaa, niin havaitaan (funktion hwisok avulla) että sen 1024 suurimmalla arvolla hwsqrt alkaakin laskea väärin. Tämä pyöristysvirhe voidaan korjata funktiolla sqrt64. Nyt olemme saavuttaneet tavoitteemme: Funktio isqrt on määritelty kaikille Haskellin mukana tuleville kokonaislukutyypeille siten, että jokainen niistä käyttää nopeaa funktiota hwsqrt mikäli mahdollista. Jos ohjelmoija määrittelee oman kokonaislukutyyppinsä, niin sillekin tulee automaattisesti oikean tuloksen joskin hitaasti antava isqrt, koska tämä uusi tyyppi liittyy tyyppiluokkaan Integral jolle teimme vastaavan säännön. Ohjelmoija voi ottaa käyttöön myös tälle uudelle tyypilleen nopeamman funktion hwsqrt kirjoittamalla vastaavan instancen. 85

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

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

Funktionimien kuormitus. TIES341 Funktio ohjelmointi 2 Kevät 2006

Funktionimien kuormitus. TIES341 Funktio ohjelmointi 2 Kevät 2006 Funktionimien kuormitus TIES341 Funktio ohjelmointi 2 Kevät 2006 Kertausta ongelma Mikä on (+) operaattorin tyyppi? Num a => a -> a -> a Mikä on (==) operaattorin tyyppi? Eq a => a -> a -> a Mikä on show

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

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 Antti-Juhani Kaijanaho Jyväskylän yliopisto Tietotekniikan laitos 10. tammikuuta 2008 Arvot... ovat laskutoimituksen lopputuloksia... ovat lausekkeita, joihin

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

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

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

15. Ohjelmoinnin tekniikkaa 15.1

15. Ohjelmoinnin tekniikkaa 15.1 15. Ohjelmoinnin tekniikkaa 15.1 Sisällys For-each-rakenne. Geneerinen ohjelmointi. Lueteltu tyyppi enum. 15.2 For-each-rakenne For-rakenteen variaatio taulukoiden ja muiden kokoelmien silmukoimiseen:

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 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

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

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

Tietueet. Tietueiden määrittely

Tietueet. Tietueiden määrittely Tietueet Tietueiden määrittely Tietue on tietorakenne, joka kokoaa yhteen eri tyyppistä tietoa yhdeksi asiakokonaisuudeksi. Tähän kokonaisuuteen voidaan viitata yhteisellä nimellä. Auttaa ohjelmoijaa järjestelemään

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

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

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

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

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

koska sellainen vaaditaan jotta oma tyyppimme Tree k t pääsee jäseneksi Luokkaan Eq.

koska sellainen vaaditaan jotta oma tyyppimme Tree k t pääsee jäseneksi Luokkaan Eq. Määritellään esimerkkinä hakupuillemme sellainen samuus x == y joka pätee täsmälleen silloin kun puissa x ja y on samat(avain,tietoalkio)-parit riippumatta siitä minkä muotoisia puut x ja y ovat. Olemme

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

Java-kielen perusteet

Java-kielen perusteet Java-kielen perusteet Tunnus, varattu sana, kommentti Muuttuja, alkeistietotyyppi, merkkijono, Vakio Tiedon merkkipohjainen tulostaminen Ohjelmointi (ict1tx006) Tunnus (5.3) Javan tunnus Java-kirjain Java-numero

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 19.1.2011 T-106.1208 Ohjelmoinnin perusteet Y 19.1.2011 1 / 39 Haluatko antaa palautetta luennoista? Ilmoittaudu mukaan lähettämällä ilmainen tekstiviesti Vast

Lisätiedot

15. Ohjelmoinnin tekniikkaa 15.1

15. Ohjelmoinnin tekniikkaa 15.1 15. Ohjelmoinnin tekniikkaa 15.1 Sisällys For-each-rakenne. Lueteltu tyyppi enum. Override-annotaatio. Geneerinen ohjelmointi. 15.2 For-each-rakenne For-rakenteen variaatio taulukoiden ja muiden kokoelmien

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

ELM GROUP 04. Teemu Laakso Henrik Talarmo

ELM GROUP 04. Teemu Laakso Henrik Talarmo ELM GROUP 04 Teemu Laakso Henrik Talarmo 23. marraskuuta 2017 Sisältö 1 Johdanto 1 2 Ominaisuuksia 2 2.1 Muuttujat ja tietorakenteet...................... 2 2.2 Funktiot................................

Lisätiedot

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista.

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista. 1 Luokka Murtoluku uudelleen Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista. Sievennettäessä tarvitaan osoittajan ja nimittäjän suurin yhteinen tekijä (syt).

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

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

Ohjelmointi 2. Jussi Pohjolainen. TAMK» Tieto- ja viestintäteknologia , Jussi Pohjolainen TAMPEREEN AMMATTIKORKEAKOULU Ohjelmointi 2 Jussi Pohjolainen TAMK» Tieto- ja viestintäteknologia Tietotyypeistä C++ - kielessä useita tietotyyppejä Kirjaimet: char, wchar_t Kokonaisluvut: short, int, long Liukuluvut: float, double

Lisätiedot

Algoritmit 1. Luento 6 Ke Timo Männikkö

Algoritmit 1. Luento 6 Ke Timo Männikkö Algoritmit 1 Luento 6 Ke 25.1.2017 Timo Männikkö Luento 6 Järjestetty lista Listan toteutus dynaamisesti Linkitetyn listan operaatiot Vaihtoehtoisia listarakenteita Puurakenteet Binääripuu Järjestetty

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 peruskurssi Y1

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

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

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

Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python 8. marraskuuta 2010 Ohjelmointi Perusteet Peruskäsitteitä Olio-ohjelmointi Pythonin alkeet Esittely Esimerkkejä Muuttujat

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

Diskreetin matematiikan perusteet Laskuharjoitus 2 / vko 9

Diskreetin matematiikan perusteet Laskuharjoitus 2 / vko 9 Diskreetin matematiikan perusteet Laskuharjoitus 2 / vko 9 Tuntitehtävät 9-10 lasketaan alkuviikon harjoituksissa ja tuntitehtävät 13-14 loppuviikon harjoituksissa. Kotitehtävät 11-12 tarkastetaan loppuviikon

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

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

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

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

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

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

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python 31. tammikuuta 2009 Ohjelmointi Perusteet Pythonin alkeet Esittely Esimerkkejä Muuttujat Peruskäsitteitä Käsittely

Lisätiedot

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

Geneeriset tyypit. TIES542 Ohjelmointikielten periaatteet, kevät Antti-Juhani Kaijanaho. Jyväskylän yliopisto Tietotekniikan laitos 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?

Lisätiedot

Ydin-Haskell Tiivismoniste

Ydin-Haskell Tiivismoniste Ydin-Haskell Tiivismoniste Antti-Juhani Kaijanaho 8. joulukuuta 2005 1 Abstrakti syntaksi Päätesymbolit: Muuttujat a, b, c,..., x, y, z,... Tyyppimuuttujat α, β, γ,... Koostimet (data- ja tyyppi-) C, D,...,

Lisätiedot

12. Monimuotoisuus 12.1

12. Monimuotoisuus 12.1 12. Monimuotoisuus 12.1 Sisällys Johdanto. Periytymismekanismi määrittää alityypityksen. Viitteiden sijoitus ja vertailu. Staattinen ja dynaaminen luokka. Myöhäinen ja aikainen sidonta. Parametrinvälitys

Lisätiedot

Tämä tarina on Fibonaccin lukujen ongelman alkuperäinen muotoilu.

Tämä tarina on Fibonaccin lukujen ongelman alkuperäinen muotoilu. Rekursiosta ja iteraatiosta Oletetaan että meillä on aluksi yksi vastasyntynyt kanipari, joista toinen on uros ja toinen naaras. Kanit saavuttavat sukukypsyyden yhden kuukauden ikäisinä. Kaninaaraan raskaus

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

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

Algoritmit 2. Luento 3 Ti Timo Männikkö

Algoritmit 2. Luento 3 Ti Timo Männikkö Algoritmit 2 Luento 3 Ti 21.3.2017 Timo Männikkö Luento 3 Järjestäminen eli lajittelu Kekorakenne Kekolajittelu Hajautus Yhteentörmäysten käsittely Ketjutus Algoritmit 2 Kevät 2017 Luento 3 Ti 21.3.2017

Lisätiedot

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset 815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 3 vastaukset Harjoituksen aiheena ovat imperatiivisten kielten muuttujiin liittyvät kysymykset. Tehtävä 1. Määritä muuttujien max_num, lista,

Lisätiedot

System.out.printf("%d / %d = %.2f%n", ekaluku, tokaluku, osamaara);

System.out.printf(%d / %d = %.2f%n, ekaluku, tokaluku, osamaara); Kysy Karilta tai Kimmolta, jos tehtävissä on jotain epäselvää. Kerro WETOon liittyvät ongelmat suoraan Jormalle sähköpostitse (jorma.laurikkala@uta.fi). Muista nimetä muuttujat hyvin sekä kommentoida ja

Lisätiedot

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

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

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

Algoritmit 2. Luento 3 Ti Timo Männikkö

Algoritmit 2. Luento 3 Ti Timo Männikkö Algoritmit 2 Luento 3 Ti 20.3.2018 Timo Männikkö Luento 3 Järjestäminen eli lajittelu Kekorakenne Kekolajittelu Hajautus Yhteentörmäysten käsittely Ketjutus Algoritmit 2 Kevät 2018 Luento 3 Ti 20.3.2018

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

20. Javan omat luokat 20.1

20. Javan omat luokat 20.1 20. Javan omat luokat 20.1 Sisällys Application Programming Interface (API). Pakkaukset. Merkkijonoluokka String. Math-luokka. Kääreluokat. 20.2 Java API Java-kielen Application Programming Interface (API)

Lisätiedot

Sisällys. 20. Javan omat luokat. Java API. Pakkaukset. java\lang

Sisällys. 20. Javan omat luokat. Java API. Pakkaukset. java\lang Sisällys 20. Javan omat luokat Application Programming Interface (API). Pakkaukset. Merkkijonoluokka String. Math-luokka. Kääreluokat. 20.1 20.2 Java API Java-kielen Application Programming Interface (API)

Lisätiedot

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä Ohjelmoinnin peruskurssien laaja oppimäärä Luento 4: Symbolit, derivojaesimerkki, kierroksen 1 ratkaisut (mm. SICP 2.32.3.2) Riku Saikkonen 1. 11. 2011 Sisältö 1 Symbolit ja sulkulausekkeet 2 Lisää Schemestä:

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

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1 Ohjelmoinnin peruskurssi Y1 CS-A1111 13.9.2017 CS-A1111 Ohjelmoinnin peruskurssi Y1 13.9.2017 1 / 19 Oppimistavoitteet: tämän luennon jälkeen osaat kirjoittaa Python-ohjelman, joka pyytää käyttäjältä lukuja,

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

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

2. Lisää Java-ohjelmoinnin alkeita. Muuttuja ja viittausmuuttuja (1/4) Muuttuja ja viittausmuuttuja (2/4) 2. Lisää Java-ohjelmoinnin alkeita Muuttuja ja viittausmuuttuja Vakio ja literaalivakio Sijoituslause Syötteen lukeminen ja Scanner-luokka 1 Muuttuja ja viittausmuuttuja (1/4) Edellä mainittiin, että String-tietotyyppi

Lisätiedot

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A274615 JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A274615 JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++? JAVA-OHJELMOINTI 3op A274615 JAVAN PERUSTEET LYHYT KERTAUS Teemu Saarelainen teemu.saarelainen@kyamk.fi Lähteet: http://java.sun.com/docs/books/tutorial/index.html Vesterholm, Kyppö: Java-ohjelmointi,

Lisätiedot

Python-ohjelmointi Harjoitus 2

Python-ohjelmointi Harjoitus 2 Python-ohjelmointi Harjoitus 2 TAVOITTEET Kerrataan tulostuskomento ja lukumuotoisen muuttujan muuttaminen merkkijonoksi. Opitaan jakojäännös eli modulus, vertailuoperaattorit, ehtorakenne jos, input-komento

Lisätiedot

Ohjelmointi 1 Taulukot ja merkkijonot

Ohjelmointi 1 Taulukot ja merkkijonot Ohjelmointi 1 Taulukot ja merkkijonot Jussi Pohjolainen TAMK Tieto- ja viestintäteknologia Johdanto taulukkoon Jos ohjelmassa käytössä ainoastaan perinteisiä (yksinkertaisia) muuttujia, ohjelmien teko

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

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1 Ohjelmoinnin peruskurssi Y1 CS-A1111 14.9.2016 CS-A1111 Ohjelmoinnin peruskurssi Y1 14.9.2016 1 / 19 Oppimistavoitteet: tämän luennon jälkeen osaat kirjoittaa Python-ohjelman, joka pyytää käyttäjältä lukuja,

Lisätiedot

Algoritmit 1. Luento 10 Ke Timo Männikkö

Algoritmit 1. Luento 10 Ke Timo Männikkö Algoritmit 1 Luento 10 Ke 14.2.2018 Timo Männikkö Luento 10 Algoritminen ongelmanratkaisu Suunnittelumenetelmät Raaka voima Järjestäminen eli lajittelu Kuplalajittelu Lisäyslajittelu Valintalajittelu Permutaatiot

Lisätiedot

815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 5 Vastaukset

815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 5 Vastaukset 815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 5 Vastaukset Harjoituksen aiheena ovat aliohjelmat ja abstraktit tietotyypit sekä olio-ohjelmointi. Tehtävät tehdään C-, C++- ja Java-kielillä.

Lisätiedot

Sisällys. 6. Metodit. Oliot viestivät metodeja kutsuen. Oliot viestivät metodeja kutsuen

Sisällys. 6. Metodit. Oliot viestivät metodeja kutsuen. Oliot viestivät metodeja kutsuen Sisällys 6. Metodit Oliot viestivät metodeja kutsuen. Kuormittaminen. Luokkametodit (ja -attribuutit).. Metodien ja muun luokan sisällön järjestäminen. 6.1 6.2 Oliot viestivät metodeja kutsuen Oliot viestivät

Lisätiedot

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo 15.2.2006

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo 15.2.2006 TURUN YLIOPISTO DEMO III Informaatioteknologian laitos tehtävät Olio-ohjelmoinnin perusteet / Salo 15.2.2006 1. Tässä tehtävässä tarkastellaan erääntyviä laskuja. Lasku muodostaa oman luokkansa. Laskussa

Lisätiedot

7. Näytölle tulostaminen 7.1

7. Näytölle tulostaminen 7.1 7. Näytölle tulostaminen 7.1 Sisällys System.out.println- ja System.out.print-operaatiot. Tulostus erikoismerkeillä. Edistyneempää tulosteiden muotoilua. 7.2 Tulostusoperaatiot System.out.println-operaatio

Lisätiedot

Kielioppia: toisin kuin Javassa

Kielioppia: toisin kuin Javassa Object Pascal Pascal kielen oliolaajennus (Inprise/Borland:n oma) luokat Voit uudelleenkäyttää luomiasi objekteja esim. komponentteja Periytyminen Kielioppia: toisin kuin Javassa Ei eroa isojen ja pienien

Lisätiedot

17. Javan omat luokat 17.1

17. Javan omat luokat 17.1 17. Javan omat luokat 17.1 Sisällys Application Programming Interface (API). Pakkaukset. Merkkijonoluokka String. Math-luokka. Kääreluokat. 17.2 Java API Java-kielen Application Programming Interface (API)

Lisätiedot

8.5 Takarekursiosta. Sanoimme luvun 8.3 foldl -esimerkissämme että

8.5 Takarekursiosta. Sanoimme luvun 8.3 foldl -esimerkissämme että 85 Takarekursiosta Sanoimme luvun 83 foldl -esimerkissämme että foldl :: (a -> b -> a) -> a -> [b] -> a foldl f z [] = z foldl f z (x:xs) = foldl f (f z x) xs olisi pelkkä silmukka Tämä johtuu siitä, että

Lisätiedot

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä Ohjelmoinnin peruskurssien laaja oppimäärä Luento 5: Sijoituslause, SICP-oliot, tietorakenteen muuttaminen (mm. SICP 33.1.3, 3.33.3.2) Riku Saikkonen 6. 11. 2012 Sisältö 1 Muuttujan arvon muuttaminen:

Lisätiedot

useampi ns. avain (tai vertailuavain) esim. opiskelijaa kuvaavassa alkiossa vaikkapa opintopistemäärä tai opiskelijanumero

useampi ns. avain (tai vertailuavain) esim. opiskelijaa kuvaavassa alkiossa vaikkapa opintopistemäärä tai opiskelijanumero Alkioiden avaimet Usein tietoalkioille on mielekästä määrittää yksi tai useampi ns. avain (tai vertailuavain) esim. opiskelijaa kuvaavassa alkiossa vaikkapa opintopistemäärä tai opiskelijanumero 80 op

Lisätiedot

Harjoitus 3 (viikko 39)

Harjoitus 3 (viikko 39) Mikäli tehtävissä on jotain epäselvää, laita sähköpostia vastuuopettajalle (jorma.laurikkala@uta.fi). Muista nimetä muuttujat hyvin sekä kommentoida ja sisentää koodisi. Vältä liian pitkiä rivejä. Ohjelmointitehtävien

Lisätiedot

17. Javan omat luokat 17.1

17. Javan omat luokat 17.1 17. Javan omat luokat 17.1 Sisällys Application Programming Interface (API). Pakkaukset. Merkkijonoluokka String. Math-luokka. Kääreluokat. 17.2 Java API Java-kielen Application Programming Interface (API)

Lisätiedot

Java-kielen perusteet

Java-kielen perusteet Java-kielen perusteet String-merkkijonoluokka 1 Ohjelmointikielten merkkijonot Merkkijonot ja niiden käsittely on välttämätöntä ohjelmoinnissa Valitettavasti ohjelmointikielten tekijät eivät tätä ole ottaneet

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

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

System.out.printf("%d / %d = %.2f%n", ekaluku, tokaluku, osamaara);

System.out.printf(%d / %d = %.2f%n, ekaluku, tokaluku, osamaara); Mikäli tehtävissä on jotain epäselvää, laita sähköpostia vastuuopettajalle (jorma.laurikkala@uta.fi). Muista nimetä muuttujat hyvin sekä kommentoida ja sisentää koodisi. Ohjelmointitehtävien osalta palautetaan

Lisätiedot

Algoritmit 2. Luento 7 Ti Timo Männikkö

Algoritmit 2. Luento 7 Ti Timo Männikkö Algoritmit 2 Luento 7 Ti 4.4.2017 Timo Männikkö Luento 7 Joukot Joukko-operaatioita Joukkojen esitystapoja Alkiovieraat osajoukot Toteutus puurakenteena Algoritmit 2 Kevät 2017 Luento 7 Ti 4.4.2017 2/26

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

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1 Ohjelmoinnin peruskurssi Y1 CS-A1111 12.9.2018 CS-A1111 Ohjelmoinnin peruskurssi Y1 12.9.2018 1 / 19 Oppimistavoitteet: tämän luennon jälkeen osaat kirjoittaa Python-ohjelman, joka pyytää käyttäjältä lukuja,

Lisätiedot

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1 Ohjelmoinnin peruskurssi Y1 CS-A1111 11.9.2019 CS-A1111 Ohjelmoinnin peruskurssi Y1 11.9.2019 1 / 19 Oppimistavoitteet: tämän luennon jälkeen osaat kirjoittaa Python-ohjelman, joka pyytää käyttäjältä lukuja,

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

niin järjestys on tämä: ensin kerto- ja jakolaskut vasemmalta oikealle, sen jälkeen plus- ja miinuslaskut vasemmalta oikealle.

niin järjestys on tämä: ensin kerto- ja jakolaskut vasemmalta oikealle, sen jälkeen plus- ja miinuslaskut vasemmalta oikealle. Alkeistason matikkaa Plus-, miinus-, kerto- ja jakolaskujen laskujärjestys Esim. jos pitää laskea tällainen lasku:? niin järjestys on tämä: ensin kerto- ja jakolaskut vasemmalta oikealle, sen jälkeen plus-

Lisätiedot

58131 Tietorakenteet ja algoritmit (kevät 2016) Ensimmäinen välikoe, malliratkaisut

58131 Tietorakenteet ja algoritmit (kevät 2016) Ensimmäinen välikoe, malliratkaisut 58131 Tietorakenteet ja algoritmit (kevät 2016) Ensimmäinen välikoe, malliratkaisut 1. Palautetaan vielä mieleen O-notaation määritelmä. Olkoon f ja g funktioita luonnollisilta luvuilta positiivisille

Lisätiedot

Ohjelmoinnin perusteet Y Python

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

Lisätiedot

Diskreetin matematiikan perusteet Laskuharjoitus 1 / vko 8

Diskreetin matematiikan perusteet Laskuharjoitus 1 / vko 8 Diskreetin matematiikan perusteet Laskuharjoitus 1 / vko 8 Tuntitehtävät 1-2 lasketaan alkuviikon harjoituksissa ja tuntitehtävät 5- loppuviikon harjoituksissa. Kotitehtävät 3-4 tarkastetaan loppuviikon

Lisätiedot

Ohjelmoinnin perusteet, syksy 2006

Ohjelmoinnin perusteet, syksy 2006 Ohjelmoinnin perusteet, syksy 2006 Esimerkkivastaukset 1. harjoituksiin. Alkuperäiset esimerkkivastaukset laati Jari Suominen. Vastauksia muokkasi Jukka Stenlund. 1. Esitä seuraavan algoritmin tila jokaisen

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

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

Uusi näkökulma. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Uusi näkökulma. TIEA341 Funktio ohjelmointi 1 Syksy 2005 Uusi näkökulma TIEA341 Funktio ohjelmointi 1 Syksy 2005 Aloitetaan alusta... Otetaan uusi näkökulma Haskelliin ohjelmointi laskentana kertausta toisaalta, uusia käsitteitä toisaalta helpottanee sitten

Lisätiedot