[(i + 1,()),(i + 2,()),(i + 3,()),...,(n,())] alkuun.
|
|
- Marja-Leena Virtanen
- 8 vuotta sitten
- Katselukertoja:
Transkriptio
1 Tällaista lisäparametria acc kutsutaan kerääjäksi (accumulator) koska siihen kerätään laskennan tulosta. Haluttu tehokkuus seuraa siitä, että nyt esimerkissämme pari (i,()) lisätäänkin oikeanpuoleisen alipuun tuottaman listan alkuun. Tämä acc sisältää [(i + 1,()),(i + 2,()),(i + 3,()),...,(n,())] ahkerassa ohjelmointikielessä laiskassa ohjelmointikielessä lausekkeen, joka tuottaa tarvittaessa tämän listan. Tällainen laiska acc on yksinkertainen erikoistapaus siitä yleisestä ideasta, että lisäparametrina saadaan se, miten laskentaa pitää jatkaa tästä eteenpäin ennen kuin laskenta on kokonaan lopussa. Yleisesti tämä idea on, että... lisäparametrina välitetäänkin funktioita t -> u joissa t on nykyisen lausekkeen ja u koko laskennan tuottaman arvon Tyyppi. liitännäisenä operaationa onkin tällaisten kuvausten yhdistäminen (.). neutraalialkiona tällä (.) on identtinen kuvaus id x = x jonka Prelude määrittelee. Tällaisia lisäfunktioita kutsutaan jatkeiksi (continuation) ja tätä ohjelmointityyliä jatkeenvälitystyyliksi (Continuation Passing Style (CPS). Näitä jatkeita käytetään esimerkiksi ohjelmointikielten... semantiikassa määriteltäessä funktionaaliseen tyyliin sellaisten rakenteiden semantiikkaa, joissa ohjelman kontrollivuo eteneekin poikkeuksellisella tavalla toteutuksissa sisäisesti vaikkapa tällaisissa rakenteissa. Esimerkiksi ohjelmointikielen Java kontrollirakenteen try... catch... finally... voi ajatella niin, että Java käyttää ohjelmoijalta piilossa kahta eri jatketta: Oletusjatke kuvaa miten normaali suoritus etenee tästä eteenpäin. Poikkeusjatke kuvaa miten suorituksen pitääkin edetä poikkeuksen (exception) tapahduttua perusjatkeen sijaan. Silloin catchillä ohjelmoidaan sitä poikkeusjatketta, jota tryn aikana käytetään. Ohjelmointikielen Scheme standardi määrittelee, että Scheme-ohjelma voi manipuloida toteutuksen sisäisiä jatkeita täysin samoin kuin tavallisia funktioita (first-class continuations). 58
2 Nimetyt kentät Haskellin data-tyypeissä Konstruktorin kenttiin viitataan Hahmoissa niiden sijainnin perusteella: 1 ensimmäinen kenttä on heti Konstruktorin jälkeen 2 toinen kenttä heti sen jälkeen 3 kolmas kenttä heti niiden jälkeen,... ja niin edelleen. Tämä vaikeuttaa ohjelmien ylläpitoa niiden kasvaessa: Muutos Konstruktorin kenttiin vaatisi jokaisen sitä käyttävän Hahmon päivittämistä ohjelmakoodissa. Siksi Haskell sallii myös Konstruktorin kenttien nimeämisen data-määritelmän yhteydessä. Jos Konstruktorin kentille antaa nimet, niin silloin niihin voidaan viitata myös näillä nimillä niiden sijainnin lisäksi. Syntaksi on Konstruktori { nimi_1 :: Tyyppi_1, nimi_2 :: Tyyppi_2, nimi_3 :: Tyyppi_3,..., nimi_q :: Tyyppi_q jossa määritellään tuttuun tapaan tämä Konstruktori sille q kenttää jokaiselle näistä kentistä i sen Tyyppi_i ja lisäksi myös nimi_i. Näitä aaltosulkuja {... ja pilkkuja, ei voi jättää pois sisentämällä koodiaan, koska ne ilmaisevat että nyt käytetään kentännimiä. Muistisääntö: aaltosulut ja puolipisteet voi korvata sisennyksellä, mutta pilkut pitää kirjoittaa. Lausekkeena kentän nimi_i on funktio joka palauttaa vastaavan kentän i arvon. Saman data-määritelmän eri Konstruktorit saavat käyttää samoja kentännimiä kunhan niillä kaikilla on täsmälleen sama Tyyppi jotta tämännimisellä funktiolla on tämä täsmällinen tulostyyppi. Eri data-määritelmät eivät saa käyttää samoja kentännimiä samasta syystä. 59
3 Jos tämän funktion parametrilla ei olekaan tämännimistä kenttää, niin seurauksena onkin suoritusaikainen virhe. Nyt voidaan kirjoittaa Hahmoja muotoa Konstruktori { nimi_i = Hahmo_i, nimi_j = Hahmo_j joista saa jättää pois osan Konstruktorin kentistä Haskell lisää jokaisen pois jätetyn kentän kohdalle hahmon _ eli sivuuttaa ne. Nyt voidaan kirjoittaa arvonluontilausekkeita muotoa Konstruktori { nimi_i = lauseke_i, nimi_j = lauseke_j Siitä saa jättää pois osan Konstruktorin kentistä. Haskell lisää jokaisen pois jätetyn kentän kohdalle lausekkeen undefined. Prelude määrittelee sen niin, että sen sievennys johtaa suoritusaikaiseen virheeseen. Voidaan kirjoittaa myös arvonluontilausekkeita muotoa lauseke { nimi_i = lauseke_i, nimi_j = lauseke_j Siinä oletetaan, että lauseke tuottaa sellaisen arvon, jolla on tämännimiset kentät. Jos niin on, tuloksena on muuten samanlainen arvo kuin lauseke paitsi että jokaisen mainitun kentän nimi_i arvona onkin vastaava lauseke_i. Jos niin ei olekaan, seuraa suoritusaikainen virhe. data Tree t = Empty Node { left :: Tree t, key :: Int, item :: t, right :: Tree t deriving (Show) -- Tässä luodaan melkein samanlaisia arvoja kuin this. additem :: Int -> t -> Tree t -> Tree t additem newkey newitem Empty = Node { left = Empty, key = newkey, item = newitem, right = Empty 60
4 additem newkey newitem key = oldkey newkey < oldkey = this { left = additem newkey newitem $ left this newkey > oldkey = this { right = additem newkey newitem $ right this otherwise = this { item = newitem -- Tässä käytetään yhä kenttien sijainteja. build :: [(Int,t)] -> Tree t build = foldr (uncurry additem) Empty itemof :: Int -> Tree t -> Maybe t itemof _ Empty = Nothing itemof newkey this@node { key = oldkey newkey < oldkey = itemof newkey $ left this newkey > oldkey = itemof newkey $ right this otherwise = Just $ item this contentsof :: Tree t -> [(Int,t)] contentsof Empty = [] contentsof this@node{ = contentsof (left this) ++ (key this,item this) : contentsof (right this) contentsof :: Tree t -> [(Int,t)] contentsof = let cont Empty acc = acc cont this@node{ acc = cont (left this) $ (key this,item this) : cont (right this) acc in flip cont [] Uusvanhat tyypit Jos data-määritelmässä data Uusi = Ainoa Vanha on vain yksi konstruktori jolla on vain yksi kenttä niin silloin se voidaankin kirjoittaa newtype Uusi = Ainoa Vanha 61
5 Tämä newtype on eräänlainen datan ja typen välimuoto. Tyypinpäättelyn aikana tämä Uusi tyyppi käsitellään datan tapaan, eli kokonaan uutena tyyppinä jonka arvojoukko on siis A suurin Uusi = { Ainoa x: x A suurin Vanha { Uusi. Siten tämä Uusi tyyppi on tyyppiturvallinen, koska sen ja Vanhan tyypin lausekkeita ei voi sekoittaa keskenään. Suorituksen aikana se käsitelläänkin typen tapaan, eli uutena lyhennenimenä tälle Vanhalle tyypille, jonka arvojoukko onkin siis A suurin Uusi = A suurin Vanha. Siten tämä Uusi tyyppi onkin itse asiassa sama kuin Vanha, eli sen Ainoa konstruktori katoaa. newtype Stack t = IntoStack { fromstack :: [t] deriving (Show) emptystack :: Stack t emptystack = IntoStack [] push :: t -> Stack t -> Stack t push x = IntoStack. (x :). fromstack pop :: u -> (t -> Stack t -> u) -> Stack t -> u pop e _ (IntoStack []) = e pop _ f (IntoStack (x:xs)) = f x (IntoStack xs) Esimerkiksi Haskell-listoja voisi mainiosti käyttää pinoina mutta se pitää tehdä tyyppiturvallisesti: listafunktioita kuten foldr ei saakaan soveltaa niihin pinoihin, joita käytetään listoina. newtype soveltuu juuri tähän: Se takaa käännösaikaisen tyyppiturvallisuuden ilman suoritusaikaista lisärasitetta. Edellisessä määritelmässä konstruktori IntoStack :: [t] -> Stack t on samalla funktio jolla listasta voi tehdä pinon. kentännimi fromstack :: Stack t -> [t] on samalla funktio jolla pinosta voi tehdä listan. 62
6 Suoritusaikana kumpaakaan niistä ei enää ole, joten nämä tyyppiturvalliset pinooperaatiot ovat yhtä tehokkaita kuin tavallinen listojenkäsittely. Pinosta poppaava koodi on lähes aina muotoa 1 if pino on tyhjä 2 käsittele tämä (virhe)tilanne jotenkin 3 else poppaa siitä päällimmäinen alkio käsiteltäväksi joten esitetään tämä yleinen idiomi turvallisena poppina, jonka argumentit ovat 1 mitä tehdään, jos pino 3 onkin tyhjä laiskuuden perusteella tämä virheenkäsittelylauseke suoritetaan vain jos näin on 2 mitä tehdään pinosta 3 popatulle alkiolle ja jäljelle jääneelle pinolle 3 pino josta yritetään popata. Kumpikin näistä haaroista 1 ja 2 tuottaa samaa tyyppiä u olevan tuloksen. Olemme tässä käyttäneet samaa suunnittelutapaa kuin esimerkiksi Preluden funktiossa maybe :: b -> (a -> b) -> Maybe a -> b 4.5 Heikko päänormaalimuoto Nyt täsmennetään, miten case-hahmonsovitus etenee laiskasti. Ajatellaan, että jokainen tietoalkio on luotu jollakin Konstruktorilla. Esimerkiksi ajatellaan, että jokainen Integer-vakio olisi oma Konstruktorinsa eli ikään kuin olisi määritelty data Integer = jolla on äärettömän monta (parametritonta) konstruktoria. Määritellään se normaalimuoto, jota laiskat ohjelmointikielet kuten Haskell käytännössä laskevat, kun ne käsittelevät näitä Konstruktoriensa luomia tietoalkioita. Haskell-lauseke on heikossa päänormaalimuodossa (Weak Head Normal Form, WHNF) jos se on... funktio \ x ->... heikkous tarkoitti sitä, ettei funktioiden sisältä etsitä redeksejä kutsu muotoa nimi arg_1 arg_2 arg_3... arg_k jonka nimi on Konstruktori tai jokin sisäänrakennettu perusoperaatio kuten (+) mutta sillä ei ole tarpeeksi argumentteja jotta se voitaisiin suorittaa eli kyseessä on sittenkin funktio. 63
7 tietoalkio samaa muotoa, mutta jossa tämännimisellä Konstruktorilla onkin tarpeeksi argumentteja jolloin se onkin suoritettu, ja sitä vastaava tietoalkio luotu. Näitä argumentteja ei oleteta normalisoiduiksi eli myös Konstruktorien kentät ovat laiskoja. Jos lauseke ei ole mitään funktiotyyppiä, niin case lauseke of Konstruktori Hahmo_1 Hahmo_2 Hahmo_3... Hahmo_k ->... suoritetaan seuraavasti: 1 lauseke sievennetään WHNF-muotoon jotta nähdään onko sen Konstruktori sama kuin Hahmossa. 2 Jos on, niin sen WHNF-muoto on Konstruktori kenttä_1 kenttä_2 kenttä_3... kenttä_k ja jatketaan sovittamalla jokainen kenttä_i sitä vastaavaan Hahmo_ion tällä samalla tavalla. 3 Jos ei ole, niin jatketaan seuraavan case-haaran Hahmoon, ja yritetään sovittaa sitä tällä samalla tavalla, ja niin edelleen. Jos lauseke taas on jotakin funktiotyyppiä, niin sille voi kirjoittaa vain triviaalisti sopivia Hahmoja, eli muuttujat tai _. Haskell-ohjelmoija voi jossain määrin ohjata milloin tämä Hahmonsovitus tapahtuu. Hahmonsovitusta voi viivyttää Hahmolla muotoa Hahmo_i koska se ja vastaava kenttä_i ohitetaan nykyisessä Hahmonsovituksessa. 1 Ne sovitetaan toisiinsa vasta silloin jos Hahmo_in antamia muuttujannimiä käytetään myöhemmin. 2 Jos se sovitus silloin epäonnistuu, niin seuraa suoritusaikainen virhe. Haskell-ohjelmoija tarvitsee tätä viivytettyä Hahmonsovitusta vain harvoin, mutta Haskell-toteutus käyttää sitä usein sisäisesti. Hahmonsovitusta voi kiirehtiä huutomerkillä!. Sen intuitiivinen lukutapa on tämän voi tehdä ahkerasti. Tarkkaan ottaen kyse on lausekkeiden WHNF-normalisoinnista jo etukäteen ennen kuin niiden informaatiota tarvitaan, mikä on eri asia kuin aito ahkeruus. Prelude määrittelee 2 funktionkutsuoperaattoria: Laiska ($) tarkoittaa aivan samaa kuin tavallinen funktionkutsu, mutta sen assosiatiivisuus säästää sisäkkäisiä sulkuja, kuten Taulukossa 1. 64
8 Ahkera ($!) lisäksi WHNF-normalisoikin kutsuttavaan funktioon lähtevän argumentin jo nyt kutsuhetkellä, eikä vasta silloin jos kutsuttava funktio sen informaatiota tarvitsee. Siten tämä ($!) on intuitiivisesti ikään kuin ahkera funktionkutsu. Haskell-standardin data-määritelmässä Konstruktorin kentän Tyyppi voidaan kirjoittaa muodossa!(tyyppi) Ympröivät sulut (...) voi jättää pois, jos niiden sisällä oleva Tyyppi on yksiosainen kuten Int. Haskell käyttää näille kentille funktionkutsuoperaattoria ($!) mutta tavallisille kentilleen tavallista operaattoria ($). Tällainen kenttä on siis intuitiivisesti ahkera. Tavallinen käyttökohde on hakupuuesimerkkimme Node-Konstruktorin rekursiiviset kentät 1 ja 4 sen vasemmalle ja oikealle alipuulle, koska tavoitteenamme on rakentaa ihan tavallinen hakupuu johon ei tarvita laiskuutta. Lisäksi ghc toteuttaa kielilaajennuksen BangPatterns joka mahdollistaa Hahmon muotoa! Hahmo Hahmonsovituksen aikana sitä vastaava kenttä WHNF-normalisoidaan joka tapauksessa, vaikka Hahmonsovitus ei sitä vaatisikaan. Erityisesti siis Hahmolla muotoa! muuttuja WHNF-normalisoidaan vastaava kenttä ja nimetään sen tulos muuttujaksi vaikka tavallisesti muuttujan esiintyminen Hahmossa antaakin vain nimen vastaavalle lausekkeelle normalisoimatta sitä vielä. Intuitiivisesti näin voi siis esittää ahkeran Hahmon ja muuttujan. Kaikkien näiden huutomerkkien! taustalla on Haskelliin lisätty primitiivifunktio seq :: a -> b -> b jonka WHNF-normalisointi etenee seuraavasti: 1 ensin WHNF-normalisoidaan sen ensimmäinen argumentti 2 sitten WHNF-normalisoidaan sen toinen argumentti ja palautetaan sen antama tulos vaikka argumentin 2 WHNF-normalisointi ei tarvitsisikaan argumentin 1 WHNFnormalisointia. Argumentin 1 WHNF-normalisointi on siis seq-kutsun sivuvaikutus. seq siis luo keinotekoisen tietoriippuvuuden argumenttiensa 1 ja 2 välille. 65
9 seq ei noudata λ-laskennan periaatteita, joten sitä käyttävää koodia ei voikaan vapaasti käsitellä koodiyhtälöillä. Esimerkiksi η-konversio ei pädekään, koska Tämän vuoksi Haskell-ohjelma kannattaa seq seq (\ x -> ). ensin kehittää ilman huutomerkkejä! (ja seqiä) lopuksi optimoida lisäämällä huutomerkkejä! tarpeen mukaan. Riittää lisätä! muutamaan strategiseen paikkaan ohjelmakoodissa, koska Haskell-kääntäjän tiukkuusanalyysi (strictness analysis) päättelee niiden perusteella, missä muissa kohdissa olisi myös voinut olla!. Laiska suoritus muodostaa lausekkeita odottamaan, tarvitaanko niiden tuloksia myöhemmin. Huutomerkillä! voi ilmoittaa kyllä, sitä tullaan tarvitsemaan myöhemmin, joten sen voi laskea jo nyt. Huutomerkillä! voi nopeuttaa Haskell-koodia, koska on nopeampaa laskea lausekkeen tulos heti kuin muodostaa ensin lauseke odottamaan ja laskea sen tulos myöhemmin kunhan ei tule laskeneeksi mitään sellaista jonka laiskuus olisi jättänyt laskematta... Ajansäästöä tärkeämpi optimointi on tilansäästö: Odottamaan jääneet lausekkeet varaavat muistia, jonka voi vapauttaa laskemalla niiden tuloksen. Esimerkiksi foldr (+) 0 [1..10ˆ7] muodostaa lausekkeen 1+(2+(3+(...+(10ˆ7+0)...))) ennen kuin laskee sen tuloksen foldl (+) 0 [1..10ˆ7] muodostaa lausekkeen (...(((0+1)+2)+3)+...)+10ˆ7 ennen kuin laskee sen tuloksen foldl (+) 0 [1..10ˆ7] WHNF-normalisoi välituloksen joka kierroksellaan: foldl (+) 0 [1..10ˆ7] = foldl (+) 1 [2..10ˆ7] = foldl (+) 3 [3..10ˆ7] = foldl (+) 6 [4..10ˆ7] =... joten se kuluttaa paljon vähemmän muistia ja myös muistinhallintaan kuluvaa aikaa. Useilla muillakin kirjastofunktioilla on myös tällainen ahkerampi versio. 66
10 4.6 Valmiiden ohjelmamodulien käyttöönotto Haskell standardi määrittelee Preludea laajemman kokoelman standardikirjastoja. Esimerkiksi foldl on kirjastossa Data.List. Haskell Platform sisältää niiden lisäksi monia muitakin kirjastoja. Esimerkiksi Control.DeepSeq sisältää funktion deepseq joka normalisoi argumenttinsa 1 kokonaan eikä vain WHNF-muotoon. Oman lähdekooditiedoston alussa (eli ennen sen ensimmäistä omaa määritelmää) voi ottaa niitä käyttöön lauseella import [qualified] Modulin.Nimi [as Lyhenne] jonka [hakasulkeissa] olevat osat ovat valinnaisia. Se tuo käyttöön kirjastossa nimeltä Modulin.Nimi tehdyt julkiset määritelmät kahdessa eri muodossa: pitkässä muodossa Modulin.Nimi.määritelty ja lyhyessä muodossa joka on pelkkä määritelty. Sama asia voi olla määritelty monessa eri modulissa, joten eri importit voivat tuoda sille käyttöön monta eri määritelmää yhtä aikaa nykyiseen lähdekooditiedostoosi. Haskell sallii monta yhtäaikaista määritelmää samalle asialle......mutta tällaista moneen kertaan määriteltyä asiaa et voi käyttää lähdekoodissasi, koska Haskellin pitää tietää mitä määritelmää tarkoitat. Siksi qualified tuokin käyttöön modulin sisältämät määritelmät vain pitkässä muodossa. Sen jälkeen eri määritelmät eroavat toisistaan, koska jokaisella on edessään vastaavan Modulin.Nimi. Jos tämä pitkä muoto Modulin.Nimi.määritelty tuntuu liian pitkältä, niin as Lyhenne sallii sen kirjoittamisen Lyhenne.määritelty. 5 Monimuotoisuus Monimuotoisuus (polymorfia, polymorphism) tarkoittaa funktionaalisessa ohjelmoinnissa sitä, että samaa funktiota voi soveltaa erityyppisiin arvoihin. Sen vastakohta on monomorfia eli yksimuotoisuus. Monimuotoisuus säästää suunnitteluohjelmointi- ja testaustyötä koska kertaalleen laadittuja tietorakenteita ja niiden funktioita voidaan käyttää yhä uudelleen eri tilanteissa. 67
11 Esimerkiksi määrittelimme yhden kerran tyyppikonstruktorin Tree :: * -> * ja saimme hakupuut sen tyyppiparametrin eri arvoille, kuten Tree Bool, Tree Int, Tree (Tree String),..., eli kaikille mahdollisille tietoalkiokentän eri tyypeille. Monimuotoisuutta on monenlaista riippuen siitä, millaista samankaltaisuutta halutaan esittää: Alityyppimonimuotoisuus (subtype polymorphism) järjestää tyypit alityyppihierarkiaan. Tyypille ja sen kaikille alityypeille yhteiset piirteet riittää esittää vain yhden kerran tyypissä itsessään, josta alityypit perivät (inherit) ne. Esimerkiksi jos hauki on kala niin silloin alityypillä hauki on myös kaikki tyypille kala määritellyt ominaisuudet. Luokkaperustaisessa olio-ohjelmoinnissa kuten Javassa olioluokat mudostavat tällaisen luokkahierarkian. Parametrinen monimuotoisuus (parametric polymorphism) Tyypeillä voi olla tyyppiparametreja, kuten t hakupuuesimerkissämme. Niiden avulla voi määritellä funktion, joka toimii aina samalla tavalla näistä eri tyypeistä t riippmatta. Esimerkiksi uuden parin(avain,sen tietoalkio) lisääminen additem tehdään aina samalla tavalla riippumatta tietoalkioiden nykyisestä tyypistä t. Funktionaalisen ohjelmoinnin ulkopuolella tätä kutsutaan geneerisyydeksi (genericity, generics). Esimerkiksi Javaan geneerisyys on lisätty kielen kehityksen kuluessa, jotta sitä ei tarvinnut enää teeskennellä epätyydyttävästi kielen oliopiirteillä. Tässä ja nyt -monimuotoisuus (ad hoc polymorphism) Haskellissa Tämä ad hoc ei ole halventava nimitys. Se on parametrisen monimuotoisuuden vastinpari : Sama funktio voidaan määritellä toimimaan eri tavalla eri tyypeille. Esimerkiksi monella eri tyypillä on järjestysrelaatio (<=) mutta Inteillä se on eri relaatio kuin Booleilla, jne. (Ja yritys vertailla esimerkiksi Inttiä ja Boolia toisiinsa on tyyppivirhe.) Silloin voidaan määritellä yhden kerran vaikkapa funktio järjestä tämä lista niin, että se käyttää listan alkiotyypin omaa järjestysrelaatiota. Luokkaperustaisessa olio-ohjelmoinnissa kuten Javassa perityn metodin uudelleenmäärittely aliluokassa on tällaista monimuotoisuutta. Javassa on myös rajapinnat (interface) tällaisen monimuotoisuuden esittämiseen luokkahierarkiasta riippumatta. ei ole käsitettä alityyppi eikä siten myöskään alityyppimonimuotoisuutta. Siten sivuutamme sen tällä kurssilla. on HM-tyypinpäättely joka tarjoaa luontevan ja automaattisen parametrisen monimuotoisuuden. 68
12 on lisännyt HM-tyypinpäättelyyn tässä ja nyt -monimuotoisuuden. Nämä tyyppiluokat (type class) ovat Haskellin oma erityispiirre. Funktionaalisen ja olio-ohjelmoinnin yhdistävät hybridi- tai moniparadigmaohjelmointikielet kuten Scala ( ja OCaml (http: //ocaml.org/) ovat puolestaan yhdistäneet tyypinpäättelyn ja alityypit. 5.1 Parametrinen monimuotoisuus Olemme nähneet tyyppiparametrit type-ja data-määritelmissä. Javassa tyyppiparametrit kirjoitetaan kulmasulkujen <...> sisään. Esimerkiksi tyyppi Lista jonka alkiot ovat Int kirjoitetaan Javassa List<Int>. Haskellin HM-tyypinpäättely automatisoi parametrisen monimuotoisuuden: Kun ohjelmoija... määrittelee uuden funktion, niin HM päättelee sille automaattisesti sellaisen pääasiallisen tyypin, jossa on tyyppiparametrit. käyttää parametrisesti monimuotoista funktiota ohjelmassaan, niin HM täydentää sen tyyppiparametreille vastaavat arvot automaattisesti käyttöyhteyden perusteella. Esimerkiksi tutun funktion foldr _ z [] = z foldr f z (x:xs) = f x (foldr f z xs) tyypinpäättely voisi edetä seuraavasti (jossa välivaiheita on yhdistelty): 1 Koska foldr saa 3 parametria, niin sen tyypin pitää olla foldr :: a -> b -> c -> d jossa emme vielä tiedä, mitä tyyppejä nämä a, b, c ja d ovat, joten pidetään ne tyyppimuuttujina joiden arvot saattavat selvitä tyypinpäättelyn jatkuessa eteenpäin. 2 Koska foldr n []-haara palauttaa sen 2. parametrin z niin sen tyypin b pitää olla sama tyyppi kuin d. Siis: foldr :: a -> b -> c -> b Näin tyypitys tarkentuu päättelyn edetessä. 3 Koska foldr n 3. parametri on lista, niin sen tyypin c pitää olla jokin listatyyppi [e] jossa e on sen alkioiden tyyppi. Siis: x :: e xs :: [e] foldr :: a -> b -> [e] -> b 4 Koska foldr n parametria f kutsutaan, niin sen täytyy olla jotakin funktiotyyppiä. Koska tämän funktion f kutsun 1. argumentti on x 69
13 2. argumentti on samaa tyyppiä b kuin foldr n tulos tulos on sekin samaa tyyppiä b kuin foldr n tulos niin syöttämällä nämä tiedot sen tyyppiin a saamme foldr :: (e -> b -> b) -> b -> [e] -> b ja foldr n tyypinpäättely on valmis, koska olemme löytäneet tyypin jokaiselle siinä esiintyvälle muuttujalle ja lausekkeelle. Tyypinpäättelyn ei tarvinnut täsmentää foldr n tyyppiin jääneitä muuttujia b ja e millään tavalla. Ne voidaan yleistää (generalize) tarkoittamaan mitä tahansa mielivaltaista tyyppiä. Siten foldr on parametrisesti monimuotoinen niiden suhteen. HM-tyypinpäättelyn a parametrisen monimuotoisuuden yhdistävä periaate: HM-tyypinpäättely päättelee annetulle lausekkeelle pääasiallisen tyypin siten, että tyyppimuuttujia rajoitetaan mahdollisimman vähän eli vain sen verran kuin on välttämätöntä tyypinpäättelyn läpiviemiseksi. Päätelty tyyppi jätetään parametrisesti monimuotoiseksi niiden tyyppimuuttujien suhteen, joita tyypinpäättelyn ei tarvinnut rajoittaa eli mahdollisimman yleiseksi. Standardi-Haskellissa tällaiset tyypit, joissa on tyyppimuuttujia, kuten foldr :: (e -> b -> b) -> b -> [e] -> b ovat siis parametrisesti monimuotoisia niiden suhteen. ghc sallii laajennuksia kuten ExplicitForAll, Rank2Types tai RankNTypes joilla voi kirjoittaa foldr :: forall b e. (e -> b -> b) -> b -> [e] -> b eli esitellä parametrisen monimuotoisuuden muodossa kaikille tyypeille b ja e. Standardi-haskellissa katsotaan siis olevan hiljainen forall tyypin alussa. Silloin monimuotoisen lausekkeen käyttöönotto voidaan katsoa olevan tämän (mahdollisesti hiljaisen) forallin poistamista korvaamalla sen sitomat muuttujat tuoreilla tyyppimuuttujilla eli sellaisilla, joita ei ole käytetty missään muualla. Esimerkiksi lausekkeen foldr ((:). g) [] tyypinpäättely 1 ottaa siinä käytettyjen muuttujien jokaiselle esiintymälle sen monimuotoisen tyypin: (.) :: forall a b c. (b -> c) -> (a -> b) -> a -> c (:) :: forall a. a -> [a] -> [a] [] :: forall a. [a] foldr :: forall a b. (a -> b -> b) -> b -> [a] -> b g :: forall a. a 70
14 2 korvaa niiden forallit tuoreilla tyyppimuuttujilla: (.) :: (q -> r) -> (p -> q) -> p -> r (:) :: s -> [s] -> [s] [] :: [t] foldr :: (u -> v -> v) -> v -> [u] -> v g :: w 3 päättelee niiden väliset riippuvuudet, tässä q = s r = [s] -> [s] w = p -> s u = p v = [s] t = s 4 päättelee niiden perusteella koko lausekkeen tyypiksi [p] -> [s] Jos lauseketta käytettiin määritelmässä map g = foldr ((:). g) [] niin näiden tietojen perusteella saadaan pääteltyä, että map :: (p -> s) -> [p] -> [s] joka voidaan yleistää map :: forall p s. (p -> s) -> [p] -> [s] jota voidaan käyttää muun tyypinpäättelyn askeleessa 1, ja niin edelleen. Jos määritelmä olisi ollut rekursiivinen, eli määriteltävä map olisi esiintynyt määrittelevässä lausekkeessa, niin se olisi voitu käsitellä kuten g eli olettaa sillekin aluksi tuntematon tyyppi. Tällaista HM-tyypinpäättelyn tuomaa parametrista monimuotoisuutta kutsutaan myös nimellä let-monimuotoisuus koska let määritelmät in lauseke (ja where) käsitellään 1 ensin päättelemällä tyypit jokaiselle määritelmälle 2 sitten yleistämällä edellisessä askeleessa 1 saadut tyypit mutta vain sellaisten muuttujien suhteen, jotka syntyivät vasta askeleessa 1 3 lopuksi päättelemällä ja vastaamalla se tyyppi, jonka lauseke saa, kun nämä paikalliset määritelmät ovat siinä parametrisesti monimuotoisia askeleen 2 tuloksena. Tyypinpäättely ilman tätä let-yleistysaskelta 2 on nopeaa. 71
15 Algoritmisesti kyse on samasta asiasta kuin (ensimmäisen kertaluvun) samastus (unification). Samastus on keskeinen operaatio esimerkiksi mekaanisessa teoreemantodistuksessa. Samastus on lineaarista syötteensä pituuden suhteen. Siten myös tämä yksinkertainen tyypinpäättely on lineaarista tarkasteltavan lausekkeen pituuden suhteen. Tämän let-yleistysaskeleen 2 lisääminen vaikeuttaa sitä rajusti onneksi vain periaatteessa. Siitä tulee PSPACE-täydellistä eli se on yksi vaikeimmista laskentaongelmista, joka voidaan ratkaista polynomisella eli realistisella määrällä muistia. Mutta johon luultavasti kuluu epärealistinen määrä aikaa... Onneksi se on hidasta vain sen suhteen, montako sisäkkäistä let-määritelmäosaa let a = let b = let c =... in lauseke_c in lauseke_b in lauseke_a ohjelmakoodissa on. Yleensä näitä tasoja on vain muutama ja se on OK. Onneksi tyypinpäättely on käytännössä lineaarista näiden sisäkkäisten inosien suhteen koska ne voivat olla pitkiäkin. Intuitiivisesti sisennetty ohjelmakoodi on usein pitkää mutta harvoin leveää. 5.2 Tyyppiluokat Täysi parametrinen monimuotoisuus on usein liian kova vaatimus, ja vaatii täsmentämistä. Mikä esimerkiksi olisi monimuotoinen tyyppi funktiolle sort, joka järjestää syötteenä saamansa listan alkiot suuruusjärjestykseen? Täysi parametrinen monimuotoisuus ei päde. sort :: forall t. [t] -> [t] On olemassa sellaisiakin tyyppejä, joilla ei ole mielekästä suuruusjärjestyksen (<=) käsitettä. Ei esimerkiksi liene hyvää määritelmää käsitteelle funktioiden välinen suuruusjärjestys. Haluamme siis sanoa jokaiselle sellaisella tyypille t jolle on määritelty (<=). Haskellissa tämä sanotaan sort :: forall t. (Ord t) => [t] -> [t] 72
16 Loogisesti => voidaan lukea kuten implikaationuoli jota se esittää: Jokaiselle tyypille t, jos t kuuluu tyyppiluokkaan Ord, niin... Se voidaan lukea myös rajoitteena niille t joita forall koskee: Jokaiselle tyyppiluokkaan Ord kuuluvalle tyypille t... Tämä tyyppiluokka Ord eli Ordered types puolestaan vaatii juuri sen, että jokaisella siihen kuuluvalla tyypillä t pitää olla määritelty se (<=) :: t -> t -> Bool Koska tyyppiluokan Ord jokaisella eri jäsenellä t on oma versionsa tästä samasta (<=) on kyseessä ad hoc -monimuotoisuus. Tämä (mahdollisesti hiljaisen) forallin ja tyypin väliin laitettava rajoite (constraint) on muotoa (fakta,fakta,fakta,...,fakta) => Sen jokainen fakta on muotoa Tyyppiluokka muuttuja jonka muuttuja on jokin forallin sitomista tyyppimuuttujista. Tällainen fakta vaatii siis, että sen muuttujan arvoksi saa valita vain jonkin sellaisen tyypin joka kuuluu tähän Tyyppiluokkaan. Niiden monikko vaatii, että jokaisen niistä pitää olla voimassa. Haskell sallii tällaiset rajoitteet monissa muissakin paikoissa joissa käsitellään tyyppimuuttujia. ghc sisältää monenlaisia syntaktisia ja semanttisia laajennuksia tähän perusideaan. Javassa voidaan asettaa vastaavia rajoituksia sen geneerisille tyyppiparametreille oliohierarkian suhteen: Arvojen pitää olla tämän luokan yli/aliluokkia. Tehdään hakupuuesimerkistämme entistä monikäyttöisempi vaihtamalla kiinteän avaintyypin Int tilalle tyyppiparametri k. Silloin on lisättävä myös rajoite (Ord k) => jokaiseen funktioon, jossa vertaillaan avaimia. Myös build on sellainen funktio, vaikka se ei itse vertailekaan avaimia: Se kutsuu funktiota additem joka vertailee. contentsof ei kuitenkaan tarvitse rajoitetta, koska siinä ei käytetä tyypin k järjestystä. Tällainen Tyyppiluokka on Haskellin vastine Javan interfacelle. Tyyppi liittyy jäseneksi Tyyppiluokkaan toteuttamalla sen vaatimat metodit kuten Ord vaatii metodin (<=). Ne eivät ole spesifikaatio- vaan ohjelmointikieliä, joten ne tarkistavat näiden metodien tyypit, mutta eivät niiden toiminnan järkevyyttä. 73
17 data Tree k t = Empty Node { left :: Tree k t, key :: k, item :: t, right :: Tree k t deriving (Show) additem :: (Ord k) => k -> t -> Tree k t -> Tree k t additem newkey newitem Empty = Node { left = Empty, key = newkey, item = newitem, right = Empty additem newkey newitem this@node{ key = oldkey newkey < oldkey = this { left = additem newkey newitem $ left this newkey > oldkey = this { right = additem newkey newitem $ right this otherwise = this { item = newitem build :: (Ord k) => [(k,t)] -> Tree k t build = foldr (uncurry additem) Empty itemof :: (Ord k) => k -> Tree k t -> Maybe t itemof _ Empty = Nothing itemof newkey this@node { key = oldkey newkey < oldkey = itemof newkey $ left this newkey > oldkey = itemof newkey $ right this otherwise = Just $ item this contentsof :: Tree k t -> [(k,t)] contentsof Empty = [] contentsof this@node{ = contentsof (left this) ++ (key this,item this) : contentsof (right this) contentsof :: Tree k t -> [(k,t)] contentsof = let cont Empty acc = acc 74
18 Java Jokainen olio kuuluu johonkin luokkaan. Sama luokka toteuttaa (implements) erilaisia rajapintoja. Olio varmaankin perii rajapintatoteutuksensa luokkahierarkiasta Javan säännöillä? Geneerisyyttä voi rajoittaa luokkahierarkian suhteen. Haskell Jokaisella arvolla on jokin tyyppi. Sama tyyppi on erilaisten tyyppiluokkien jäsen eli instanssi (instance). Arvon tyyppi määrää sen instanssit. Haskell-ohjelmoija esittää ne säännöt joilla hänen omalle data-tyyppikonstruktorilleen määrätään sen instanssit. Parametrista monimuotoisuutta voi rajoittaa tyyppiluokilla. Taulukko 2: Javan rajapinnat vs. Haskellin tyyppiluokat. cont acc = cont (left this) $ (key this,item this) : cont (right this) acc in flip cont [] Haskell on laajentanut HM-tyypinpäättelyään siten, että se automatisoi myös näitä Tyyppiluokkarajoitteita: Se kerää rajoitteita tyypinpäättelyn aikana. Jos esimerkiksi lausekkeessa on (<=) x jossa x :: t niin se lisää rajoitteisiin vastaavan faktan Ord t.... sieventää rajoitteita tyypinpäättelyn aikana. Jos esimerkiksi havaitaan että t=[u] niin rajoite saa muodon Ord [u] joka sieventyy muotoon Ord u koska listatyypillä on järjestys jos (ja vain jos) sen alkiotyypillä on....käsittelee rajoitteet, joissa ei enää ole muuttujia. Jos esimerkiksi u=(int,char) niin rajoite saa muodon Ord (Int,Char) joten vertailuun käytetään nyt ad hoc -monimuotoisen (<=) versiota (<=) :: [(Int,Char)] -> [(Int,Char)] -> Bool jonka Haskell tuottaa.... muistaa ne pääasiallisessa yleistämässään parametrisesti monimuotoisessa tyypinpäättelyn lopputuloksessa. Taulukko 2 vertailee Javan rajapintoja ja Haskellin tyyppiluokkia. 5.3 Automaattinen jäsenyys Haskell voi liittää tyypin automaattisesti jäseneksi joihinkin tyyppiluokkiin. Sen tekee data-määritelmän ylimääräinen deriving-rivi data Uusi =... deriving (Luokka,Luokka,Luokka,...,Luokka) 75
19 sanoo, että tämä Uusi tyyppi liittyy jäseneksi jokaiseen siinä mainittuun Luokkaan sillä lailla miten tähän Luokkaan tavallisesti liitytään. Toisin sanoen, Haskell tuottaa jokaiselle oletusarvoisen määrittelyn instance Luokka Uusi where... automaattisesti, eikä ohjelmoijan tarvitse kirjoittaa sellaista itse käsin. Ohjelmoija voi kirjoittaa sellaisen itsekin käsin, jos hän haluaakin tehdä sen jotenkin toisin kuin Haskell sen tekisi. Tätä deriving-mekanismia voi käyttää data-määritelmissä vain 6 standardityyppiluokan kanssa: Eq eli ne tyypit, joiden arvoilla on samuusvertailu (==). Se tavallinen tapa tutkia onko x == y on: 1 Onko niillä sama konstruktori? 2 Jos on, niin onko myös niiden kentillä samat arvot? Useimmiten se onkin juuri se oikea tapa vertailla tyypin arvojen samuutta. Siten deriving (Eq,...) on useimmiten juuri se mitä halutaan. Toisaalta esimerkiksi hakupuille tämä tavallinen tapa testaisi ovatko nämä hakupuut täsmälleen saman muotoisia Niille voisi siis olla mielekkäämpää kirjoittaa käsin semanttisempi samuusehto eli sisältävätkö ne täsmälleen samat (avain,tietoalkio)- parit joka ei riipu puiden muodosta. Ord eli ne tyypit, joiden arvoilla on suuruusjärjestysvertailu (<=). Se tavallinen tapa suuruusjärjestää data-määritelmä on järjestää arvot niin, että vertaillaan 1 ensin eri konstruktorit ylhäältä alas 2 sitten saman konstruktorin kentät vasemmalta oikealle niiden kirjoitusjärjestyksessä. Siten data Maybe t = Nothing Just t deriving (Ord,...) järjestää niin, että 1 Nothing < Just mitä tahansa 2 Just x < Just y on x < y. Hakupuut ovat esimerkki tyypistä, jolla ei ole luontevaa suuruusjärjestyksen käsitettä. Show eli ne tyypit, joiden arvot voi tulostaa merkkijonoksi. Tämä tulostusmetodi on nimeltään show. Aiemmin käyttämämme deriving (Show) siis sanoo tämän tyypin arvot voi tulostaa merkkijonoksi ja ghci käyttää tätä metodia show näyttääkseen ne käyttäjälle. Se tavallinen tapa tulostaa arvo on samalla tavalla kuin data-määritelmässä kirjoitettiin. 76
20 Read eli ne tyypit joiden arvon voi lukea merkkijonosta. Tämä lukumetodi on nimeltään read. deriving (Eq,Show,Read) toteuttavat ehdon read (show x) == x jokaiselle äärelliselle arvolle x (read-write invariance). Tätä metodia read käytettäessä sen tulokselle on annettava monomorfinen tyyppi, jotta tiedetään täsmälleen minkä tyyppistä arvoa nyt luetaan. Tämä metodi read ei korvaa oikeaa jäsennysfunktiota (parser) koska se on hidas pitkillä merkkijonoilla eikä käsittele kirjoitusvirheitä niissä käyttäjäystävällisesti. Bounded eli ne tyypit joilla on pienin ja suurin arvo. Pienimmän arvon nimi on minbound. Suurimman arvon nimi on maxbound. Esimerkiksi minbound :: Int on pienin ohjelmoijan kokonaisluku. Enum eli ne tyypit joilla on luontevat käsitteet seuraava suurempi arvo ja edellinen pienempi arvo. Seuraavan antaa metodi succ. Esimerkiksi numeroilla succ = (+ 1). Edellisen antaa metodi pred. Näillä tyypeillä voi käyttää listanotaatiota [eka,toka..vika]. deriving (Enum,...) on mahdollista kaikille niille tyypeille, joiden yhdelläkään konstruktorilla ei ole lainkaan parametreja esimerkiksi lukutyypeille. Uusvanhan tyypin automaattinen jäsenyys vanhassa tyypissään Näitä 6 standardityyppiluokkaa voi käyttää myös määritelmässä newtype Uusi = Ainoa Vanha deriving (...) Lisäksi ghc sisältää laajennuksen GeneralizedNewtypeDeriving jolla newtypen deriving voi mainita minkä tahansa muunkin tyyppiluokan, johon sen Vanha tyyppi kuuluu. Silloin tämä Uusi tyyppi saa automaattisesti ne samat jäsenyydet kuin Vanhakin. Sillä voi ilmaista vaivattomasti että tämä Uusi tyyppi on näissä metodeissa samanlainen kuin Vanhakin ja ohjelmoija voi keskittyä kirjoittamaan vain ne funktiot joissa Uusi onkin erilainen kuin Vanha. 5.4 Jo määritellyn tyyppiluokan jäseneksi liittyminen Ohjelmoija voi liittää oman Tyyppinsä jo määriteltyyn Luokkaaan päätason määritelmällä jonka instance (faktat) => Luokka Tyyppi where... 77
21 faktat rajoittavat niitä tyyppiparametreja jotka Tyyppi sisältää. (Tämä koko rajoite voidaan jättää pois, jos se on tarpeeton.) where-osa sisältää niiden metodien, jotka tämä Luokka vaatii, toteutukset tämäntyyppiselle syötteelle. Näissä totetuksissa saa hyödyntää niitä tyyppiluokkien jäsenyyksiä jotka faktat lupasivat. Intuitiivisesti: Jos nämä faktat ovat voimassa, niin tämä Tyyppi kuuluu tuohon Luokkaaan tällä tavalla.... Ne metodit, jotka jo määritely Luokka vaatii jäseniltään, on (toivottavasti...) selostettu sen dokumentaatiossa. 78
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...
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
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
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
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:
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
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
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
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
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 :
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,
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
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:
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
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,
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
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
5.1 Tyyppiparametrit. Nyt lisäämme parametrit myös data-määrittelyihin: data Nimi tp 1 tp 2 tp 3... tp k =...
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ä
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
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/
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:
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
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ä
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
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/
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
lausekkeiden tapauksessa. Jotkin ohjelmointikielet on määritelty sellaisiksi,
3.5. TYYPIT 59 indeksit voidaan siirtää kielitasolta oliotasolle siirryttäessä alkamaan nollasta. Vain mikäli indeksin alin arvo oliotasolla ei ole tiedossa ennen suorituksen alkua, on tarpeen lisätä taulukko-olioon
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
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
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ää laskentoa. TIEA341 Funktio ohjelmointi 1 Syksy 2005
Lisää laskentoa TIEA341 Funktio ohjelmointi 1 Syksy 2005 Kertausta: Laajennettu aritmetiikka Lasketaan rationaaliluvuilla vakiot yhteen, vähennys, kerto ja jakolasku Laajennetaan sitä määrittelyillä: vakio
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:
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................................
Laiska laskenta, korekursio ja äärettömyys. TIEA341 Funktio ohjelmointi Syksy 2005
Laiska laskenta, korekursio ja äärettömyys TIEA341 Funktio ohjelmointi Syksy 2005 Muistatko graafinsievennyksen? DAG esitys ja graafinsievennys DAG esitys Lausekkeen rakennepuu, jossa yhteiset alilausekkeet
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
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
Jatkeet. TIES341 Funktio ohjelmointi 2 Kevät 2006
Jatkeet TIES341 Funktio ohjelmointi 2 Kevät 2006 Havainto: häntäkutsu (1) Funktiokutsun yleinen toimintaperiaate: (koskee vain täysiä kutsuja, ts. jotka eivät palauta funktiota) kutsuja kirjaa pinoon paluuosoitteen
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
Sisällys. JAVA-OHJELMOINTI Osa 7: Abstrakti luokka ja rajapinta. Abstraktin luokan idea. Abstrakti luokka ja metodi. Esimerkki
Sisällys JAVA-OHJELMOINTI Osa 7: Abstrakti luokka ja rajapinta Abstrakti luokka ja metodi Rajapintamäärittely (interface) Eero Hyvönen Tietojenkäsittelytieteen laitos Helsingin yliopisto 13.10.2000 E.
Algoritmit 1. Luento 3 Ti Timo Männikkö
Algoritmit 1 Luento 3 Ti 17.1.2017 Timo Männikkö Luento 3 Algoritmin analysointi Rekursio Lomituslajittelu Aikavaativuus Tietorakenteet Pino Algoritmit 1 Kevät 2017 Luento 3 Ti 17.1.2017 2/27 Algoritmien
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
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?
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ä:
Ohjelmistojen mallintaminen viikon 4 laskareiden mallivastauksia
Ohjelmistojen mallintaminen viikon 4 laskareiden mallivastauksia Tehtävä 1 Tehtävässä 1 mallinnettiin Monopolipeliä. Alla olevassa esimerkissä peliin liittyy aina 2 noppaa, peliä pelataan pelilaudalla,
811120P Diskreetit rakenteet
811120P Diskreetit rakenteet 2018-2019 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
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
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
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
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
812347A Olio-ohjelmointi, 2015 syksy 2. vsk. X Poikkeusten käsittelystä
812347A Olio-ohjelmointi, 2015 syksy 2. vsk X Poikkeusten käsittelystä Sisältö 1. Yleistä poikkeusten käsittelystä 2. Poikkeuskäsittelyn perusteita C++:ssa 3. Standardissa määritellyt poikkeukset 4. Poikkeusvarmuus
Lisää pysähtymisaiheisia ongelmia
Lisää pysähtymisaiheisia ongelmia Lause: Pysähtymättömyysongelma H missä H = { w111x w validi koodi, M w ei pysähdy syötteellä x } ei ole rekursiivisesti lueteltava. Todistus: Pysähtymisongelman komplementti
Concurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo
Concurrency - Rinnakkaisuus Group: 9 Joni Laine Juho Vähätalo Sisällysluettelo 1. Johdanto... 3 2. C++ thread... 4 3. Python multiprocessing... 6 4. Java ExecutorService... 8 5. Yhteenveto... 9 6. Lähteet...
14.1 Rekursio tyypitetyssä lambda-kielessä
Luku 14 Rekursiiviset tyypit Edellisessä luvussa esitetyt tietue- ja varianttityypit eivät yksinään riitä kovin mielenkiintoisten tietorakenteiden toteuttamiseen. Useimmissa ohjelmissa tarvitaan erilaisia
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
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
18. Abstraktit tietotyypit 18.1
18. Abstraktit tietotyypit 18.1 Sisällys Johdanto abstrakteihin tietotyyppeihin. Pino ja jono. Linkitetty lista. Pino linkitetyllä listalla toteutettuna. 18.2 Johdanto Javan omat tietotyypit ovat jo tuttuja:
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
ITKP102 Ohjelmointi 1 (6 op)
ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 12. huhtikuuta 2019 Tee kukin tehtävä omalle konseptiarkille. Noudata ohjelmointitehtävissä kurssin koodauskäytänteitä. Yksi A4-kokoinen lunttilappu
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
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
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
JFO: Johdatus funktionaaliseen ohjelmointiin
JFO: Johdatus funktionaaliseen ohjelmointiin Matti Nykänen Tietojenkäsittelytieteen laitos, Itä-Suomen yliopisto matti.nykanen@uef.fi Lukuvuosi 2010-11, IV periodi Sisältö 1 Johdanto 1 1.1 Historiaa.....................................
6 Algebralliset tietotyypit
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ä
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.
Hakupuut. tässä luvussa tarkastelemme puita tiedon tallennusrakenteina
Hakupuut tässä luvussa tarkastelemme puita tiedon tallennusrakenteina hakupuun avulla voidaan toteuttaa kaikki joukko-tietotyypin operaatiot (myös succ ja pred) pahimman tapauksen aikavaativuus on tavallisella
11.4. Context-free kielet 1 / 17
11.4. Context-free kielet 1 / 17 Määritelmä Tyypin 2 kielioppi (lauseyhteysvapaa, context free): jos jokainenp :n sääntö on muotoa A w, missäa V \V T jaw V. Context-free kielet ja kieliopit ovat tärkeitä
11/20: Konepelti auki
Ohjelmointi 1 / syksy 2007 11/20: Konepelti auki Paavo Nieminen nieminen@jyu.fi Tietotekniikan laitos Informaatioteknologian tiedekunta Jyväskylän yliopisto Ohjelmointi 1 / syksy 2007 p.1/11 Tämän luennon
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
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,
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
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.
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
ITKP102 Ohjelmointi 1 (6 op)
ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 20. huhtikuuta 2018 Vastaa kaikkiin tehtäviin. Tee kukin tehtävä omalle konseptiarkille. Noudata ohjelmointitehtävissä kurssin koodauskäytänteitä.
Kehittää ohjelmointitehtävien ratkaisemisessa tarvittavia metakognitioita!
Kehittää ohjelmointitehtävien ratkaisemisessa tarvittavia metakognitioita! eli... Hyvä kaava sanoo enemmän kuin,... tuhat riviä koodia!... sata riviä tekstiä!... kymmenen diagrammia! Sopimusohjelmointi
14. Poikkeukset 14.1
14. Poikkeukset 14.1 Sisällys Johdanto. Tarkistettavat ja tarkistamattomat poikkeukset. Poikkeusten tunnistaminen ja sieppaaminen try-catchlauseella. Mitä tehdä siepatulla poikkeuksella? Poikkeusten heittäminen.
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")
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
Sisällys. 18. Abstraktit tietotyypit. Johdanto. Johdanto
Sisällys 18. bstraktit tietotyypit Johdanto abstrakteihin tietotyyppeihin. Pino ja jono. Linkitetty lista. Pino linkitetyllä listalla toteutettuna. 18.1 18.2 Johdanto Javan omat tietotyypit ovat jo tuttuja:
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
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
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,
13. Loogiset operaatiot 13.1
13. Loogiset operaatiot 13.1 Sisällys Loogiset operaatiot AND, OR, XOR ja NOT. Operaatioiden ehdollisuus. Bittioperaatiot. Loogiset operaatiot ohjausrakenteissa. Loogiset operaatiot ja laskentajärjestys.
TIES542 kevät 2009 Tyyppijärjestelmän laajennoksia
TIES542 kevät 2009 Tyyppijärjestelmän laajennoksia Antti-Juhani Kaijanaho 16. helmikuuta 2009 Tyypitetyt ohjelmointikielet sisältävät paljon muitakin konstruktioita kuin yksinkertaisesti tyypitetyn lambda-kielen,
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,
Olio-ohjelmoinnissa luokat voidaan järjestää siten, että ne pystyvät jakamaan yhteisiä tietoja ja aliohjelmia.
4. Periytyminen 4.1. Johdantoa Käytännössä vähänkään laajemmissa ohjelmissa joudutaan laatimaan useita luokkia, joiden pitäisi pystyä välittämään tietoa toisilleen. Ohjelmien ylläpidon kannalta olisi lisäksi
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
Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen
Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen Taulukot: Array Taulukko Javassa pitää aina perustaa (new) Yksinkertaisessa tilanteessa taulukon koko tiedetään etukäteen ja
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
Javan perusteita. Janne Käki
Javan perusteita Janne Käki 20.9.2006 Muutama perusasia Tietokone tekee juuri (ja vain) sen, mitä käsketään. Tietokone ymmärtää vain syntaksia (sanojen kirjoitusasua), ei semantiikkaa (sanojen merkitystä).
811120P Diskreetit rakenteet
811120P Diskreetit rakenteet 2016-2017 4. Joukot, relaatiot ja funktiot Osa 3: Funktiot 4.3 Funktiot Olkoot A ja B joukkoja. Funktio joukosta A joukkoon B on sääntö, joka liittää yksikäsitteisesti määrätyn
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ä
Mitä funktionaalinen ohjelmointi on
Funktionaalinen ohjelmointi Mitä funktionaalinen ohjelmointi on - Funktionaalisessa ohjelmoinnissa mallinnus keskittyy löytämään ongelmasta sellaisia tiedon muunnoksia, jotka voidaan esittää matemaattisina
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
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
Ohjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 11: Tulkin muokkaaminen, sisäiset määrittelyt, makrot (mm. SICP 3.2.4, 4-4.1.6) Riku Saikkonen 29. 11. 2012 Sisältö 1 Kirjan tulkin muokkaaminen 2 Yksityiskohta:
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ä
Groovy. Niko Jäntti Jesper Haapalinna Group 31
Groovy Niko Jäntti Jesper Haapalinna Group 31 Johdanto Groovy on Apachen kehittämä Javaan perustuva dynaaminen oliopohjainen ohjelmointikieli. Kielen kehitys alkoi vuonna 2003, versio 1.0 julkaistiin 2007
Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen
Chapel TIE-20306 Ryhmä 91 Joonas Eloranta Lari Valtonen Johdanto Chapel on Amerikkalaisen Cray Inc. yrityksen kehittämä avoimen lähdekoodin ohjelmointikieli. Chapel on rinnakkainen ohjelmointikieli, joka
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:
Sisällys. 14. Poikkeukset. Johdanto. Johdanto
Sisällys 14. Poikkeukset Johdanto. Tarkistettavat ja tarkistamattomat poikkeukset. Poikkeusten tunnistaminen ja sieppaaminen try-catchlauseella. Mitä tehdä siepatulla poikkeuksella? Poikkeusten heittäminen.