koska sellainen vaaditaan jotta oma tyyppimme Tree k t pääsee jäseneksi Luokkaan Eq.
|
|
- Tuula Salminen
- 7 vuotta sitten
- Katselukertoja:
Transkriptio
1 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 kirjoittamassa koodia funktiolle (==) :: Tree k t -> Tree k t -> Bool koska sellainen vaaditaan jotta oma tyyppimme Tree k t pääsee jäseneksi Luokkaan Eq. Kirjoitamme vain sen ohjelmakoodin emme tätä tyypitystä. Koodissamme haluamme verrata ovatko puiden x ja y contentsof-listat samat. Haluamme siis käyttää niiden välistä samuusvertailua (==) :: [(k,t)] -> [(k,t)] -> Bool eli haluamme että myös Eq [(k,t)]. Haskell päättelee, että Eq [(k,t)] vaatii Eq (k,t) joka puolestaan vaatii että Eq k ja Eq t. Koska nämä k ja t ovat tyyppimuuttujia, niin Haskell ei pysty päättelemään tämän enempää, vaan ohjelmoijan on luvattava ne kirjoittamalla samat faktat. data Tree k t = Empty Node { left :: Tree k t, key :: k, item :: t, right :: Tree k t deriving (Show) instance (Eq k,eq t) => Eq (Tree k t) where x == y = contentsof x == contentsof y 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 79
2 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 cont this@node{ acc = cont (left this) $ (key this,item this) : cont (right this) acc in flip cont [] Intuitiivisesti ohjelmoija on esittänyt säännön: Jos mielivaltaisille tyypeille k on määritelty sen oma samuus (==) :: k -> k -> Bool ja t on määritelty sen oma samuus (==) :: t -> t -> Bool niin minun tyypilleni Tree k t määritellään sen oma samuus (==) :: Tree k t -> Tree k t -> Bool niiden perusteella tällä tavalla. Päätellessään että Eq [(k,t)] Haskell käyttää samanlaisia sääntöjä instance (Eq a) => Eq [a] where... instance (Eq a,eq b) => Eq (a,b) where... ja vastaava metodi (==) :: [(k,t)] -> [(k,t)] -> Bool 80
3 käyttää niiden where-osien (==)-metodeja. Haskellin tyyppiluokilla voi siis generoida ohjelmakoodia automaattisesti HMtyypinpäättelyn sivutuotteena. Se mahdollistaa monenlaisia uusia tyyppiturvallisia ohjelmointitekniikoita. Haskellin ohjelmointifilosofiassa Tyyppi saa liittyä Luokkaan korkeintaan yhden kerran. Ajattelutapa on (jälleen) samantapainen kuin matematiikassa: tämäntyyppisillä arvoilla on vain tämä yksi oikea ja luonnollinen samuus / järjestys / tulostusasu /... ja niin edelleen. Jos liittymistapoja sallittaisiin useita, niin ei olisi enää selvää, millaista funktiota milloinkin pitäisi käyttää. Entä jos haluammekin tehdä jotenkin toisin vaikkapa vertailla merkkijonoja niin, että emme erottelekaan suuria ja pieniä kirjaimia toisistaan? Haskellin näkökulmasta sellainen on toinen tyyppi kuin tavalliset merkkijonot koska se tekee jotakin toisin. Tällaisiin tilanteisiin newtype soveltuu hyvin. import Data.Char import Data.Ord -- "Case-Insensitive Strings". newtype CIS = IntoCIS{ fromcis :: String deriving (Show) instance Ord CIS where compare = comparing (map tolower. fromcis) instance Eq CIS where (==) = ((EQ ==).). compare 5.5 Uuden tyyppiluokan määritteleminen Uusi tyyppiluokka määritellään päätasolla class (faktat) => Luokka muuttuja where metodi_1 :: Tyyppi_1 metodi_1 = lauseke_1 metodi_2 :: Tyyppi_2 metodi_2 = lauseke_2... muuttuja edustaa tähän Luokkaan kuuluvaa tuntematonta jäsentä eli tyyppiä: Tämä muuttuja kuuluu tähän Luokkaan, jos sillä on nämä metodit. 81
4 faktat rajoittavat tätä muuttujaa. (Tämä koko rajoite voidaan jättää pois, jos se on tarpeeton.) jokaisen metodin Tyyppi sisältää tämän muuttujan. (Muutenhan se ei kuulu tähän Luokkaan koska se ei käsittele muuttujatyyppisiä arvoja.) metodilla saa (mutta ei tarvitse) olla lauseke joka antaa sen oletustoteutuksen jota käytetään silloin jos jokin instance ei määrittelekään tätä metodia. Otetaan esimerkiksi tyyppiluokan Ord määrittely Preludessa. Sen muuttujana on a eli olemme määrittelemässä mitkä metodit tällä tuntemattomalla tyypillä a pitää olla jotta se kuuluisi tähän tyyppiluokkaan Ord. Sen fakta vaatii että tällä a pitää olla samuus (==). Jos x <= y && y <= x niin silloin x == y joten olisi outoa määritellä sellainen tyyppi a jolla olisi metodi (<=) mutta ei metodi (==). Haskell ei ole spesifiointi- vaan ohjelmointikieli, joten se vaatii vain että nämä metodit (<=) ja (==) on määritelty, mutta ei tarkista toimivatko ne näin. Seuraavaksi annetaan metodit ja niiden tyypit. (Siis where-osan voi järjestää kuten haluaa.) Kommentissa lukee, miten Uusi tyyppi on tarkoitus liittää tähän tyyppiluokkaan Ord: joko instance Ord Uusi where x <= y =... tai instance Ord Uusi where compare x y =... Lopuksi annetaan oletustoteutus jokaiselle metodille. Ideana on, että kun Uusi tyyppi määrittelee instancessaan joko metodinsa tai metodinsa (<=) :: Uusi -> Uusi -> Bool compare :: Uusi -> Uusi -> Ordering niin kaikki muutkin metodit tulevat samalla määritellyiksi oletustoteutustensa kautta. class (Eq a) => Ord a where compare :: a -> a -> Ordering (<), (<=), (>=), (>) :: a -> a -> Bool max, min :: a -> a -> a -- Minimal complete definition: -- (<=) or compare 82
5 -- Using compare can be more efficient for complex types. compare x y x == y = EQ x <= y = LT otherwise = GT x <= y x < y x >= y x > y = compare x y /= GT = compare x y == LT = compare x y /= LT = compare x y == GT -- note that (min x y, max x y) = (x,y) or (y,x) max x y x <= y = y otherwise = x min x y x <= y = x otherwise = y Luokkamäärittelyn sisäpuolelle pitää kirjoittaa ne metodit jotka sen jäsenet haluavat määritellä itselleen omissa instanceissaan. Ne käyttävät ad hoc -monimuotoisuutta. ulkopuolelle voi kirjoittaa ne funktiot jota määritellään samalla lailla kaikille sen jäsenille kunhan niiden tyypeissä on Luokkarajoite. Ne käyttävät parametrista monimuotoisuutta Luokkarajoitteella täsmennettynä. Luokan Ord määritelmä ei noudata tätä periaatetta tiukasti, koska sen sisällä on myös muut funktiot kuin pelkästään sen kommentissa mainitut metodit (<=) ja compare. Ne muut funktiot voi nostaa määritelmän ulkopuolelle tavallisiksi funktioiksi. class (Eq a) => Ord a where compare :: a -> a -> Ordering compare x y x == y = EQ x <= y = LT otherwise = GT (<=) :: a -> a -> Bool x <= y = compare x y /= GT (<), (>=), (>) :: forall a. (Ord a) => a -> a -> Bool x < y = compare x y == LT x >= y = compare x y /= LT x > y = compare x y == GT max, min :: forall a. (Ord a) => a -> a -> a 83
6 max x y x <= y = y otherwise = x min x y x <= y = x otherwise = y 5.6 Konstruktoriluokat Edellä kuvailimme tyyppiluokat niin, että niiden jäsenet ovat tyyppejä. Toisin sanoen niin, että class-määritelmässä muuttujan laji on *. Tyyppiluokka voi olla myös (tyyppi)konstruktoriluokka (constructor class) jolloin sen jäsenet ovatkin tyyppikonstruktoreita. Toisin sanoen, sen muuttujan laji voikin olla esimerkiksi * -> *. Konstruktoriluokat ilmaisevat tyyppikonstruktorien yhteisia ominaisuuksia samaan tapaan kuin tavalliset tyyppiluokat ilmaisevat tyyppien yhteisiä ominaisuuksia kuten kaikilla näillä tyypeillä on järjestys (<=). Preludessa on esimerkiksi tyyppiluokka class Functor f where fmap :: (a -> b) -> f a -> f b jonka muuttujan f laji on * -> * koska se ottaa yhden tyyppiparametrin a tai b antaa metodin fmap toisen parametrin tyypiksi f a ja tulostyypiksi f b. Siihen kuuluvat sellaiset tyyppikonstruktorit f joiden sisältämä informaatio (joka on tyyppiä a) voidaan korvata uudella informaatiolla (joka on tyyppiä b) käyttäen annettua muuntofunktiota (joka on siis tyyppiä a -> b). Esimerkiksi tyyppikonstruktori lista kuuluu tähän luokkaan metodinaan fmap :: (a -> b) -> [a] -> [b] fmap = map koska map g soveltaa funktiota g :: a -> b syötelistan jokaiseen alkioon ja palauttaa näin saatujen tulosten listan. Koska tyyppikonstruktorit ovat tyyppien välisiä kuvauksia, niin myös konstruktoriluokalla esitetty niiden yhteinen ominaisuus on funktioiden tasolla. Esimerkiksi tämän konstruktoriluokan Functor jäsenten pitää toteuttaa funktiotason yhtälöt fmap id = id fmap (f. g) = fmap f. fmap g 84
7 joiden intuitio on, että fmap saa muuttaa tietorakenteen sisältämää informaatiota mutta ei sen muotoa. (Koska Haskell on ohjelmointi- eikä spesifiointikieli, niin se ei tarkista onko näin.) Esimerkiksi listoissa id-säännön perusteella map ei lisää tai poista eikä edes järjestä uudelleen saamansa listan alkioita. Vastaavasti hakupuuesimerkissämme fmap g käsittelee vain lisätietokenttää item. Koska Tree :: * -> * -> * niin Tree k :: * -> * joka sopii Functorin lajiksi. data Tree k t = Empty Node { left :: Tree k t, key :: k, item :: t, right :: Tree k t deriving (Show) instance Functor (Tree k) where fmap _ Empty = Empty fmap g node = node{ left = fmap g $ left node, item = g $ item node, right = fmap g $ right node instance (Eq k,eq t) => Eq (Tree k t) where x == y = contentsof x == contentsof y 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 = 85
8 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 cont this@node{ acc = cont (left this) $ (key this,item this) : cont (right this) acc in flip cont [] 5.7 Liittyvät tyypit Aiemmissa class-määritelmissä on vain yksi muuttuja eli ne ovat määritelleet yhden tyypin ominaisuuksia. Haskellin class-määritelmässä sallitaan myös monta muuttujaa eli se voi määritellä myös monen tyypin välisiä suhteita: class R t u where... määrittelee 2-paikkaisen suhteen eli relaation R tyyppimuuttujien t ja u välille. Haskell on jo kauan sisältänyt tällaiset moniparametriset tyyppiluokat. Tavallisesti nämä tyypit kuten t ja u eivät kuitenkaan ole tasa-arvoisia keskenään, vaan yleensä yksi niistä on päätyyppi ja toiset siihen liittyviä aputyyppejä. Esimerkiksi Javassa voi määritellä luokan T sisällä siihen liittyviä apuluokkia U kuten iteraattoreita yms. Tällaiset tyyppiluokan sisällä olevat sen varsinaiseen jäseneen liittyvät (associated) tyypit ovat melko uusi ghc-laajennus Haskelliin. Kiselyov et al. (2010) esittelevät sitä. 86
9 Tähän tarkoitukseen oli jo aiemmin lainattu tietokantateoriasta funktionaaliset riippuvuudet (functional dependencies) mutta se lienevät nyt väistymässä näiden liittyvien tyyppien tieltä. Tämän piirteen mutkikas kehityshistoria johtunee siitä, että sen yhteentoiminta HMtyypinpäättelyn kanssa oli haastavaa. Sellainen tyyppiluokka joka vaatii tyyppimuuttujaltaan, että sillä on tällaisia liittyviä tyyppejä, määritellään seuraavasti: class (faktat) => Luokka muuttuja where type Nimi muuttuja :: laji data Uusi muuttuja :: laji... jossa saa siis olla montakin muuttujaa, mutta keskitymme vain yhteen. Tyyppi pääsee jäseneksi tällaiseen tyyppiluokkaan antamalla vaaditut type-, dataja metodimääritelmät instancensa sisällä. Liittyviä tyyppejä on kahdenlaisia, vastaten Haskellin kahdenlaisia tyypinmäärittelyjä: type vaatii, että tähän Luokkaan päästäkseen tyypin T pitää nimetä jokin aputyyppi U tämännimiseen rooliin mutta sen ei tarvitse olla juuri tätä varten luotu uusi tyyppi. Tätä nimettävää aputyyppiä U merkitään Nimi T. data vaatii, että tähän Luokkaan päästäkseen tyypin T pitääkin luoda itselleen uusi oma aputyyppi V. Tätä luotavaa aputyyppiä V merkitään Uusi T. Matemaattisesti sanotaan että (type ei ole mutta) data on injektiivinen (injective) koska sama V voi olla vain yhden T aputyyppinä Uusi T. Kun aputyyppi V on injektiivinen, niin Haskellin tyypinpäättely pystyy päättelemään sen käyttöyhteydestä sitä vastaavan (eli ainoan mahdollisen) päätyypin T. Luonnostellaan esimerkkinä tyyppiluokka Graph eli tyyppi g on (suunnatun) verkon jokin toteutustyyppi. Tällainen g ei selviä tehtävästään yksin, vaan se tarvitsee avukseen tyypit Vertex g solmuilleen. Määritellään se typenä, koska esimerkiksi Int on luonteva tyyppi solmuille monen eri tyypin g verkoissa, eli sen ei kannata olla injektiivinen. Edge g kaarilleen. Määritellään se datana, jotta saamme ilmaistua että tämä tyyppi on juuri tuon verkkotyypin g kaarityyppi eikä minkään muun eli injektiivisyyden. Label g kaartensa painoille, jos kyseessä on painotettu verkko. Määritelläänkin se vasta aliluokassa, koska on olemassa myös sellaisia verkkoja, joiden kaarilla ei ole painoja. 87
10 Nyt voidaan tyyppiluokan Graph metodeina vaatia myös metodeja sen aputyypeille Vertex g ja Edge g. Näiden aputyyppimetodien kuten source ja target tyypeissä mainitaan tyyppiluokan Graph muuttuja g vain epäsuorasti osana tyyppejä Vertex g ja Edge g mutta se riittää. Vaadittu ghc-laajennus on nimeltään tyyppiperheet eli TypeFamilies. Collatz on esimerkki verkosta, jossa ei ole kaaripainoja. Kaaripainottomille verkoille voidaan määritellä esimerkiksi leveyssuuntainen läpikäynti. {-# LANGUAGE TypeFamilies,FlexibleContexts #- import qualified Data.Map as Map import qualified Data.Set as Set class Graph g where type Vertex g :: * data Edge g :: * source :: Edge g -> Vertex g target :: Edge g -> Vertex g edgesfrom :: g -> Vertex g -> [Edge g] breadth1st :: (Graph g) => g -> Vertex g -> [[Edge g]] breadth1st = undefined class (Graph g) => LabeledGraph g where type Label g :: * label :: Edge g -> Label g dijkstra :: (LabeledGraph g,num (Label g)) => g -> Vertex g -> [(Vertex g,label g)] dijkstra = undefined data Collatz = Collatz instance Graph Collatz where type Vertex Collatz = Integer data Edge Collatz = CollatzEdge Integer Integer deriving (Show) source (CollatzEdge x _) = x target (CollatzEdge _ y) = y edgesfrom _ n = [CollatzEdge n $ if even n 88
11 ] then n div 2 else 3*n + 1 data DFA s = DFA{ startdfa :: s, tabledfa :: Map.Map s (Bool,Map.Map Char s) exampledfa :: DFA Int exampledfa = DFA{ startdfa = 0, tabledfa = Map.fromList [(0,(False,Map.fromList [( a,1)])),(1,(true, Map.fromList [( b,0)])) ] instance (Ord s) => Graph (DFA s) where type Vertex (DFA s) = s data Edge (DFA s) = TransitionDFA s Char s deriving (Show) source (TransitionDFA x ) = x target (TransitionDFA z) = z edgesfrom dfa state = maybe [] (map (\ (char,state ) -> TransitionDFA state char state ). Map.assocs. snd) $ Map.lookup state $ tabledfa dfa instance (Ord s) => LabeledGraph (DFA s) where type Label (DFA s) = Char label (TransitionDFA _ y _) = y data NFA s = NFA{ startnfa :: s, tablenfa :: Map.Map s (Bool,Set.Set (Char,s)) examplenfa :: NFA String examplenfa = NFA{ startnfa = "start", tablenfa = Map.fromList [("start",(false,set.fromlist [( a,"other")])),("other",(true, Set.fromList [( b,"start")])) ] 89
12 instance (Ord s) => Graph (NFA s) where type Vertex (NFA s) = s data Edge (NFA s) = TransitionNFA s Char s deriving (Show) source (TransitionNFA x ) = x target (TransitionNFA z) = z edgesfrom nfa state = maybe [] (map (\ (char,state ) -> TransitionNFA state char state ). Set.elems. snd) $ Map.lookup state $ tablenfa nfa instance (Ord s) => LabeledGraph (NFA s) where type Label (NFA s) = Char label (TransitionNFA _ y _) = y Deterministinen (DFA) ja epädeterministinen (NFA) äärellinen automaatti ovat esimerkkejä eri tavoilla toteutetuista verkoista, joissa on kaaripainot tilasiirtymien merkit. Esimerkiksi Dijkstran algoritmi voidaan määritellä sellaisille verkoille, joiden kaarilla on painot, ja ne ovat Numeerista tyyppiä. Rajoitteiden perusmuoto on pelkkä Luokka muuttuja joka ei ole riittävän joustava liittyville tyypeille. ghc-laajennus FlexibleContexts sallii kirjoittaa tämän rajoitteen muodossa Num (Label g) joka ei ole tätä perusmuotoa. Se voitaisiin kirjoittaa melkein perusmuodossa Num h, h Label g jossa käytetään toista ghc-laajennusta joka tarkoittaa, että näiden kahden tyypin pitää olla yksi ja sama tyyppi Tyyppiperheet Liittyvien tyyppien määrittely on usein käytetty erikoistapaus yleisestä tyyppiperheen määrittelystä. Tyyppiperhe on tyyppien välinen funktio: Kun kirjoitamme tavallisen funktion, Konstruktori hahmossa tutkii funktion syötteenään saamaa argumenttiarvoa ja haarautuu sen perusteella lausekkeessa tuottaa funktion tulosarvon. Vastaavasti tyyppiperheessä jokainen Tyyppi on Konstruktorin roolissa: Tyyppiperhe haarautuu eri tapauksiin syötteenään saamansa tyypin perusteella 90
13 tuottaa tuloksenaan kyseistä haaraa vastaavan tyypin. Liittyvät tyypit ovat tällaisen tyyppiperheen määrittelyä tyyppiluokan sisällä. Tyyppiperheitä voi määritellä myös niiden ulkopuolella lähdekooditiedoston päätasolla käyttämällä tarkennetta family. Tyyppiperheen oma laji (eli sen oma tyyppi ) esitellään muodossa jossa type family Nimi muuttuja :: laji data family Nimi muuttuja :: laji Nimi on sille annettu nimi. muuttuja on sen formaali parametri. Niitä saa olla useita, aivan samoin kuin tavallisella funktiolla saa olla useita parametreja, mutta keskitytään yksinkertaisuuden vuoksi vain yhteen. laji on sen tuloksen laji eli tyyppi. Toisin kuin tavallinen funktio, tyyppiperhe pitää esitellä näin: Haskell ei päättele tyyppiperheillä niin perusteellisesti kuin tavallisilla funktioilla, vaan tyytyy tarkistamaan että niiden määrittely ja käyttö vastaa tätä esittelyä. data vaatii, että Nimi on injektiivinen, kun taas type ei vaadi sitä. TämänNimisen tyyppiperheen jokainen haara kirjoitetaan muodossa type instance Nimi Sisään = Ulos data instance Nimi Sisään = Ulos jossa type tai data on sama kuin sen esittelyssä. Tällainen haara toimii Tyyppitasolla samoin kuin tavallisenkin funktion haara: Jos nykyinen Tyyppi sopii Sisään- tyyppihahmoon, niin korvaa se Ulos- tyyppilausekkeella β-reduktion periaatteen mukaan. Näin jatketaan, kunnes korvattavaa ei enää ole. Sisään ja Ulos saavat sisältää tyyppiparametreja ja -muuttujia. Tyyppiperheen määritelmä onkin avoin (toisin kuin tavallisen funktion): Tällaisia haaroja voi lisätä kaikkialla lähdekoodissa, niiden ei siis tarvitse olla peräkkäin eikä edes samassa tiedostossa. Tämä sallii sen, että uutta tyyppiä määriteltäessä määritellään samalla sille oma tyyppiperhehaaransa. Yksinkertaisena esimerkkinä määritellään kokonaislukujen tarkka kertolasku: Kun kaksi b-bittistä kokonaislukua kerrotaan keskenään, niin tulos on yksi 2 b- bittinen kokonaisluku,......mutta (*) :: (Num a) => a -> a -> a 91
14 leikkaakin tuloksen takaisin samaan b-bittiseen tyyppiin a. Määritellään siis funktio safemult :: (Integral a,integral (Twice a)) => a -> a -> Twice a jossa tyyppiperhe Twice antaa b-bittiselle kokonaislukutyypille a sen 2 b- bittisen vastintyypin. Nyt joudumme käyttämään type-perhettä, joka ei siis ole injektiivinen, koska tarvitsemme Integeria sen tulokseksi useammalle kuin yhdelle sen syötetyypille a. {-# LANGUAGE TypeFamilies,FlexibleContexts #- import Data.Int import Data.Word type family Twice t :: * type instance Twice Int8 = Int16 type instance Twice Int16 = Int32 type instance Twice Int32 = Int64 type instance Twice Int64 = Integer type instance Twice Integer = Integer type instance Twice Word8 = Word16 type instance Twice Word16 = Word32 type instance Twice Word32 = Word64 type instance Twice Word64 = Integer safemult :: (Integral a,integral (Twice a)) => a -> a -> Twice a safemult x y = (fromintegral x) * (fromintegral y) Haskell esittää tyyppiperheillä tyyppien luokilla tyyppien ja funktioiden välisiä suhteita. Ne mahdollistavat tyyppitasolla (type-level) ohjelmoinnin, jossa HM-tyypinpäättely suorittaa käännösaikaista laskentaa tyypeillä. Esimerkkinä tästä niiden yhteispelistä asetetaan seuraava ohjelmointitavoite: Annetaan funktio f :: t -> u. intotable f luo siitä laiskan tietorakenteen taulu joka sisältää kaikki sen arvot siten, että fromtable taulu x antaa vastauksenaan arvon f x jonka se on katsonut tästä taulusta. 92
15 Arvo f x lasketaan tähän tauluun vain silloin kun sitä ensimmäisen kerran kysytään. Seuraavilla kerroilla se katsotaan tästä taulusta laskematta sitä uudelleen. Toisin sanoen, kehitetään tietorakenne taulu joka muistintaa annetun funktion f. Tämän taulun oma tyyppi riippuu funktion f parametrin tyypistä t. Siten tämä riippuvuus ilmaistaan tyyppiin t liittyvänä tyyppinä eli tyyppiperheenä Table t u jossa u on funktion f tulostyyppi. Tämän taulun omasta tyypistä puolestaan riippuu se, miten sen intotable ja fromtable toteutetaan. Siten tämä riippuvuus ilmaistaan metodeina siinä tyyppiluokassa Memo t jossa myös Table t u määritellään. Lähdemme liikkeelle tietorakenteesta, josta saadaan Table t u sellaisille tyypeille t joita voi käsitellä bitti bitiltä. Erityisesti Table Integer u tarvitsee tällaisen tyypin, jonka arvot ovat laiskasti äärettömiä. Käytämme siihen ääretöntä Braunin puuta (Braun tree). Sen solmut on numeroitu 1, 2, 3,... siten, että juuresta pääsee solmuun s lukemalla sen binääriesitys s = 1d k...d 2 d 1 d 0 pienimmästä toiseksi suurimpaan bittiin eli d 0, d 1, d 2,...,d k ja valitsemalla aina vasen/oikea alipuu seuraavan bitin b i perusteella. Kun Integral-tyyppi on etumerkitön kuten Word niin sen taulun Table Word u voi toteuttaa yhdellä puulla, jonka solmuissa on arvot f 0,f 1,f 2,... etumerkillinen kuten Int niin sen taulun Table Int u voi toteuttaa kahdella puulla, joista yhdessä on arvot f 1,f 2,f 3,... ja toisessa arvot f 0,f -1,f -2,... Kuvassa 3 on tämän puun 3 ylintä tasoa. Puu jatkuu niistä alaspäin laiskasti periaatteessa äärettömyyteen. {-# LANGUAGE TypeFamilies #- import Data.Word import Data.Int import Debug.Trace -- Tämä Braunin puu on ääretön tietorakenne arvoille -- f 1,f 2,f 3,... data Braun t u = Braun { value :: u, zero :: Braun t u, one :: Braun t u 93
16 Kuva 3: Äärettömän Braunin puun 3 ylintä tasoa. growbraun :: (Integral t) => (t -> u) -> Braun t u growbraun f = let grow present past = let current = present + past future = 2 * present in Braun{ value = f current, zero = grow future past, one = grow future current in grow 1 0 lookbraun :: (Integral t) => Braun t u -> (t -> u) lookbraun b 1 = value b lookbraun b n = lookbraun ((if even n then zero else one) b) (n div 2) -- Tämä Braunin puupari on ääretön tietorakenne arvoille -- positiiviset eli f 1, f 2, f 3,... ja -- negatiiviset eli f 0, f -1, f -2,... data Brauns t u = Brauns{ positive :: Braun t u, negative :: Braun t u growbrauns :: (Integral t) => (t -> u) -> Brauns t u growbrauns f = Brauns{ positive = growbraun f, negative = growbraun $ f. (1 -) lookbrauns :: (Integral t) => Brauns t u -> (t -> u) 94
17 lookbrauns brauns n = if n>0 then lookbraun (positive brauns) n else lookbraun (negative brauns) $ 1 - n -- Funktion f :: t -> u taulukointi vaatii taulukkotyypin sen -- parametrityypille t. class Memo t where data Table t :: * -> * intotable :: (t -> u) -> Table t u fromtable :: Table t u -> (t -> u) instance Memo Word where newtype Table Word u = TableWord (Braun Word u) intotable = TableWord. growbraun. (. pred) fromtable (TableWord table) = lookbraun table. succ instance Memo Word8 where newtype Table Word8 u = TableWord8 (Braun Word8 u) intotable = TableWord8. growbraun. (. pred) fromtable (TableWord8 table) = lookbraun table. succ instance Memo Int where newtype Table Int u = TableInt (Brauns Int u) intotable = TableInt. growbrauns fromtable (TableInt table) = lookbrauns table instance Memo Int8 where newtype Table Int8 u = TableInt8 (Brauns Int8 u) intotable = TableInt8. growbrauns fromtable (TableInt8 table) = lookbrauns table instance (Memo t1,memo t2) => Memo (t1,t2) where newtype Table (t1,t2) u = TablePair (Table t1 (Table t2 u)) intotable f = 95
18 TablePair $ intotable $ \ x -> intotable (\ y -> f (x,y)) fromtable (TablePair table) (x,y) = fromtable (fromtable table x) y memoized :: (Memo t) => ((t -> u) -> (t -> u)) -> (t -> u) memoized f = let from = fromtable memo memo = intotable $ f from in from esimerkki :: Int -> Int esimerkki = memoized $ \ fact n -> trace ("lasken " ++ show n) $ if n>1 then n * fact (n-1) else 1 data vaatii, että Table t u on injektiivinen. newtype takaa sen, sehän on tyypinpäättelyssä kuin data. Se estää hyödyntämästä vaikkapa taulujen Table Word u ja Table Word8 u keskinäistä samankaltaisuutta. Memo (t1,t2) on esimerkki tyyppikonstruktorin käsittelystä. Vaaditaan, että Memo t1 ja Memo t2 eli että taulutyypit Table t1 u ja Table t2 v sekä niiden metodit intotable ja fromtable voidaan muodostaa. Silloin Memo (t1,t2) ja sen metodit intotable ja fromtable voidaan muodostaa t1-tauluna joka sisältää t2-tauluja. Nyt voimme automatisoida muistintamisen: Olkoon g :: t -> u g x = e lähdekoodi Haskell-funktiolle, josta haluamme sellaisen muistinnetun version, joka laskeen jokaisen rekursiokutsunsa vain yhden kerran. Olkoon sen parametrin tyyppi t tyyppiluokan Memo jäsen. Silloin h :: t -> u h = memoized $ \ g x -> e on sen muistinnettu versio. 1 Ensin g muuttuu funktion nimestä sen parametriksi. 96
19 2 Sitten g korvautuu funktiolla from joka kysyy tuloksensa automaattisesti luodusta taulusta memo. Idea on sama kuin kuin kiintopisteoperaattorissa (9) fix mutta tämä operaattori käyttääkin taulua. Muistinnuksen toiminnan voi varmistaa kirjastofunktiolla Debug.Trace.trace :: String -> a -> a joka tulostaa sivuvaikutuksenaan ensimmäisen parametrinsa silloin kun sen toisen parametrin sievennys alkaa. Se on siis debug-seq. esimerkkinä on muistinnettu kertomafunktio (8) fact. Tällainen muistinnus käyttää laiskuutta 2 tavalla: taulu kasvaa laiskasti sitä mukaa kun sen sisältöjä kysellään eri t-arvoilla. Nämä taulun sisällöt viittaavat takaisin tauluun itseensä Rajoitelaji Orchard and Schrijvers (2010) havaitsivat, että tyyppiperhelähestymistapa sopii myös tyyppien rajoitteille, eli implikaationuolen => vasemmalla puolella. Nykyinen ghc-laajennus on hieman toinen kuin heidän ehdotuksensa. Ideana on lisätä peruslajin * eli tyyppi rinnalle uusi peruslaji Constraint eli rajoite. Silloin voidaan kirjoittaa tyyppiperheitä joiden lajina on Constraint arvona on implikaationuolen => vasemmalle puolelle kelpaava faktamonikko faktoissa on näiden tyyppiperheiden kutsuja. Nämäkin kutsut korvataan arvoillaan, kuten tyyppiperheiden kutsut. Näin esimerkiksi tyyppiluokkaan jäseneksi liittyvä tyyppi voi lisätä sen metodien rajoitteisiin omia lisärajoitteitaan. Tämä ratkaisisi esimerkiksi sen ongelman, että matemaattisesti käsite joukko on Functor, koska operaatio on luonteva tulkinta operaatiolle fmap g S = {g(x): x S sovella funktiota g joukon S jokaiseen alkioon x ja kokoa nämä tulokset g(x) uudeksi joukoksi eli sovella funktiota g joukon S sisältöön joka on Functorin perusidea. joukkojen Haskell-kirjastototeutus Data.Set.Set ei voikaan kuulua luokkaan Functor 97
20 koska Setin toteutus olettaa tehokkuussyistä alkiotyypiltään Ordin, joten sovellettavan funktion g tulostyypinkin pitää kuulua Ordiin johon Functorin metodin fmap tyypin määritelmässä ei oltukaan varauduttu. Jos Functoria standardoitaessa olisi jo tunnettu nämä rajoitelajit, niin sen määritelmä olisi voitu lausua muodossa class Functor f where type Inv f e :: Constraint type Inv f e = () fmap :: (Inv f a,inv f b) => (a -> b) -> f a -> f b johon liittyy rajoite nimeltään Inv jonka 1 ensimmäinen tyyppiparametri on tämän luokan muuttuja f 2 toinen tyyppiparametri e edustaa sovellettavan funktion g tulostyyppiä 3 tuloksen laji onkin Constraint eikä *. Lisäksi Inville on annettu oletustoteutus () eli ei rajoitteita. Siten fmapin rajoitteen oletuksena on ((),()) => eli () => eli ei rajoitteita nykyiset instance Functor -määrittelyt säilyisivät ennallaan. 98
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ätiedotTyyppejä 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ätiedotAlgebralliset 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ätiedotFunktionimien 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ätiedotLaajennetaan 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ätiedottää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ätiedotTä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ätiedotTIEA341 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ätiedotTä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[(i + 1,()),(i + 2,()),(i + 3,()),...,(n,())] alkuun.
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
LisätiedotAbstraktit 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ätiedot5.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ä
LisätiedotTIEA341 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ätiedotLuku 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ätiedotHaskell 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ätiedotTIEA341 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ätiedotTIEA341 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ätiedotTIEA341 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ätiedotTaas 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ätiedot5.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ätiedotLuku 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ätiedot6 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ä
LisätiedotA274101 TIETORAKENTEET JA ALGORITMIT
A274101 TIETORAKENTEET JA ALGORITMIT PUURAKENTEET, BINÄÄRIPUU, TASAPAINOTETUT PUUT MIKÄ ON PUUTIETORAKENNE? Esim. Viereinen kuva esittää erästä puuta. Tietojenkäsittelytieteessä puut kasvavat alaspäin.
LisätiedotTIEA341 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ätiedotTIEA341 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ätiedotGeneeriset 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ätiedot815338A 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ätiedot5.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ätiedot811120P 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
LisätiedotELM 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ätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 7: Funktionaalista ohjelmointia (mm. SICP 3.5) Riku Saikkonen 13. 11. 2012 Sisältö 1 Laiskaa laskentaa: delay ja force 2 Funktionaalinen I/O 3 Funktionaalista
LisätiedotYdin-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ätiedotDemo 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ätiedotLaiska 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
Lisätiedot815338A 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ätiedot1.3Lohkorakenne muodostetaan käyttämällä a) puolipistettä b) aaltosulkeita c) BEGIN ja END lausekkeita d) sisennystä
OULUN YLIOPISTO Tietojenkäsittelytieteiden laitos Johdatus ohjelmointiin 81122P (4 ov.) 30.5.2005 Ohjelmointikieli on Java. Tentissä saa olla materiaali mukana. Tenttitulokset julkaistaan aikaisintaan
LisätiedotSe 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ätiedotHahmon etsiminen syotteesta (johdatteleva esimerkki)
Hahmon etsiminen syotteesta (johdatteleva esimerkki) Unix-komennolla grep hahmo [ tiedosto ] voidaan etsia hahmon esiintymia tiedostosta (tai syotevirrasta): $ grep Kisaveikot SM-tulokset.txt $ ps aux
LisätiedotTehtävä 4 : 2. b a+1 (mod 3)
Tehtävä 4 : 1 Olkoon G sellainen verkko, jonka solmujoukkona on {1,..., 9} ja jonka särmät määräytyvät oheisen kuvan mukaisesti. Merkitään lisäksi kirjaimella A verkon G kaikkien automorfismien joukkoa,
LisätiedotA ja B pelaavat sarjan pelejä. Sarjan voittaja on se, joka ensin voittaa n peliä.
Esimerkki otteluvoiton todennäköisyys A ja B pelaavat sarjan pelejä. Sarjan voittaja on se, joka ensin voittaa n peliä. Yksittäisessä pelissä A voittaa todennäköisyydellä p ja B todennäköisyydellä q =
LisätiedotRekursiolause. Laskennan teorian opintopiiri. Sebastian Björkqvist. 23. helmikuuta Tiivistelmä
Rekursiolause Laskennan teorian opintopiiri Sebastian Björkqvist 23. helmikuuta 2014 Tiivistelmä Työssä käydään läpi itsereplikoituvien ohjelmien toimintaa sekä esitetään ja todistetaan rekursiolause,
LisätiedotOhjelmointi 1 C#, kevät 2013, 2. tentti
ITKP102 Ohjelmointi 1 C# 15.5.2013 1 / 6 Ohjelmointi 1 C#, kevät 2013, 2. tentti Tentaattori Antti-Jussi Lakanen Tässä tentissä saa olla mukana omia muistiinpanoja yhden arkin verran. Tentin valvojalla
LisätiedotTKT20001 Tietorakenteet ja algoritmit Erilliskoe , malliratkaisut (Jyrki Kivinen)
TKT0001 Tietorakenteet ja algoritmit Erilliskoe 5.1.01, malliratkaisut (Jyrki Kivinen) 1. [1 pistettä] (a) Esitä algoritmi, joka poistaa kahteen suuntaan linkitetystä järjestämättömästä tunnussolmullisesta
LisätiedotOhjelmointi 1 C#, kevät 2013,
Ohjelmointi 1 C#, kevät 2013, 19.4.2013 (English versions of the questions can be requested from the supervisor. Englanninkieliset kysymykset saa pyytämällä tentin valvojalta.) Tentti (yliopisto opiskelijat)
Lisätiedot15. 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ätiedot8.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ätiedotEsimerkki: 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ätiedot2.4 Normaalimuoto, pohja ja laskentajärjestys 2.4. NORMAALIMUOTO, POHJA JA LASKENTAJÄRJESTYS 13
2.4. NORMAALIMUOTO, POHJA JA LASKENTAJÄRJESTYS 13 Toisinaan voi olla syytä kirjoittaa α- tai β-kirjain yhtäsuuruusmerkin yläpuolelle kertomaan, mitä muunnosta käytetään. Esimerkki 4 1. (λx.x)y β = y 2.
Lisätiedot811312A Tietorakenteet ja algoritmit 2015-2016. V Verkkojen algoritmeja Osa 2 : Kruskalin ja Dijkstran algoritmit
811312A Tietorakenteet ja algoritmit 2015-2016 V Verkkojen algoritmeja Osa 2 : Kruskalin ja Dijkstran algoritmit Sisältö 1. Johdanto 2. Leveyshaku 3. Syvyyshaku 4. Kruskalin algoritmi 5. Dijkstran algoritmi
LisätiedotOhjelmoinnin 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ätiedotHakupuut. 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
LisätiedotInjektio (1/3) Funktio f on injektio, joss. f (x 1 ) = f (x 2 ) x 1 = x 2 x 1, x 2 D(f )
Injektio (1/3) Määritelmä Funktio f on injektio, joss f (x 1 ) = f (x 2 ) x 1 = x 2 x 1, x 2 D(f ) Seurauksia: Jatkuva injektio on siis aina joko aidosti kasvava tai aidosti vähenevä Injektiolla on enintään
Lisätiedot5.3 Laskimen muunnelmia 5.3. LASKIMEN MUUNNELMIA 57
5.3. LASKIMEN MUUNNELMIA 57 Samaan sarjaan kuuluu seuraavakin funktio, jonka määritelmä esittelee muutenkin hyödyllisen tavan kirjoittaa ohjelmia: getline :: IO String getline = getchar λc case c of \n
Lisätiedot58131 Tietorakenteet ja algoritmit (syksy 2015) Toinen välikoe, malliratkaisut
Tietorakenteet ja algoritmit (syksy 0) Toinen välikoe, malliratkaisut. (a) Alussa puu näyttää tältä: Lisätään 4: 4 Tasapaino rikkoutuu solmussa. Tehdään kaksoiskierto ensin oikealle solmusta ja sitten
LisätiedotTietorakenteet ja algoritmit
Tietorakenteet ja algoritmit Rekursio Rekursion käyttötapauksia Rekursio määritelmissä Rekursio ongelmanratkaisussa ja ohjelmointitekniikkana Esimerkkejä taulukolla Esimerkkejä linkatulla listalla Hanoin
LisätiedotOhjelmoinnin 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ätiedot15. 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ätiedotTehtävän V.1 ratkaisuehdotus Tietorakenteet, syksy 2003
Tehtävän V.1 ratkaisuehdotus Tietorakenteet, syksy 2003 Matti Nykänen 5. joulukuuta 2003 1 Satelliitit Muunnetaan luennoilla luonnosteltua toteutusta seuraavaksi: Korvataan puusolmun p kentät p. key ja
Lisätiedot3. Hakupuut. B-puu on hakupuun laji, joka sopii mm. tietokantasovelluksiin, joissa rakenne on talletettu kiintolevylle eikä keskusmuistiin.
3. Hakupuut Hakupuu on listaa tehokkaampi dynaamisen joukon toteutus. Erityisesti suurilla tietomäärillä hakupuu kannattaa tasapainottaa, jolloin päivitysoperaatioista tulee hankalampia toteuttaa mutta
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 5: Sijoituslause, SICP-oliot, todistamisesta (mm. SICP 33.1.3, 3.33.3.2) Riku Saikkonen 7. 11. 2011 Sisältö 1 Muuttujan arvon muuttaminen: set! 2 SICP-oliot
LisätiedotTT00AA12-2016 - Ohjelmoinnin jatko (TT10S1ECD)
TT00AA12-2016 - Ohjelmoinnin jatko (TT10S1ECD) Ohjelmointikäytännöt 21/3/11 Mikko Vuorinen Metropolia Ammattikorkeakoulu 1 Sisältö 1) Mitä on hyvä koodi? 2) Ohjelmointikäytäntöjen merkitys? 3) Koodin asettelu
LisätiedotTIEA341 Funktio-ohjelmointi 1, kevät 2008
TIEA341 Funktio-ohjelmointi 1, kevät 2008 Luento 10 Todistamisesta Antti-Juhani Kaijanaho Jyväskylän yliopisto Tietotekniikan laitos 21. tammikuuta 2008 Samuuden todistaminen usein onnistuu ihan laskemalla
LisätiedotTIEA241 Automaatit ja kieliopit, kevät 2011 (IV) Antti-Juhani Kaijanaho. 19. tammikuuta 2012
TIEA241 Automaatit ja kieliopit, kevät 2011 (IV) Antti-Juhani Kaijanaho TIETOTEKNIIKAN LAITOS 19. tammikuuta 2012 Sisällys Sisällys Muistathan A B -konstruktion 0 k 1 i 2 s 3 s 4 a 5 0 k 1 o 2 i 3 r 4
LisätiedotAlgoritmit 1. Luento 13 Ti 23.2.2016. Timo Männikkö
Algoritmit 1 Luento 13 Ti 23.2.2016 Timo Männikkö Luento 13 Suunnittelumenetelmät Taulukointi Kapsäkkiongelma Ahne menetelmä Verkon lyhimmät polut Dijkstran menetelmä Verkon lyhin virittävä puu Kruskalin
LisätiedotOhjelmoinnin 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ätiedotTIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 16. marraskuuta 2015
ja ja TIEA241 Automaatit ja kieliopit, syksy 2015 Antti-Juhani Kaijanaho NFA:ksi TIETOTEKNIIKAN LAITOS 16. marraskuuta 2015 Sisällys ja NFA:ksi NFA:ksi Kohti säännöllisiä lausekkeita ja Nämä tiedetään:
LisätiedotTIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 12. marraskuuta 2015
TIEA241 Automaatit ja kieliopit, syksy 2015 Antti-Juhani Kaijanaho TIETOTEKNIIKAN LAITOS 12. marraskuuta 2015 Sisällys Muistathan A B -konstruktion 0 k 1 i 2 s 3 s 4 a 5 0 k 1 o 2 i 3 r 4 a 5 00 k 11 i
LisätiedotOhjelmoinnin 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ätiedotOhjelmoinnin 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ätiedotSisä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ätiedot1.1 Pino (stack) Koodiluonnos. Graafinen esitys ...
1. Tietorakenteet Tietorakenteet organisoivat samankaltaisten olioiden muodostaman tietojoukon. Tämä järjestys voidaan saada aikaan monin tavoin, esim. Keräämällä oliot taulukkoon. Liittämällä olioihin
Lisätiedot58131 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ätiedotLOAD R1, =2 Sijoitetaan rekisteriin R1 arvo 2. LOAD R1, 100
Tiedonsiirtokäskyt LOAD LOAD-käsky toimii jälkimmäisestä operandista ensimmäiseen. Ensimmäisen operandin pitää olla rekisteri, toinen voi olla rekisteri, vakio tai muistiosoite (myös muuttujat ovat muistiosoitteita).
Lisätiedot815338A 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ätiedotChapel. 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
LisätiedotKuvaus eli funktio f joukolta X joukkoon Y tarkoittaa havainnollisesti vastaavuutta, joka liittää joukon X jokaiseen alkioon joukon Y tietyn alkion.
Kuvaus eli funktio f joukolta X joukkoon Y tarkoittaa havainnollisesti vastaavuutta, joka liittää joukon X jokaiseen alkioon joukon Y tietyn alkion. Vastaavuus puolestaan on erikoistapaus relaatiosta.
LisätiedotMatematiikan tukikurssi
Matematiikan tukikurssi Kurssikerta 1 Määrittelyjoukoista Tarkastellaan funktiota, jonka määrittelevä yhtälö on f(x) = x. Jos funktion lähtöjoukoksi määrittelee vaikkapa suljetun välin [0, 1], on funktio
LisätiedotLuento 3: Tietorakenteiden esittäminen
Luento 3: Tietorakenteiden esittäminen AS-0.110 XML-kuvauskielten perusteet Janne Kalliola Tietorakenteiden esittäminen XML-dokumentti puuna Muunnokset muodosta toiseen Perustietorakenteet listat puut
LisätiedotOhjelmoinnin 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ätiedot58131 Tietorakenteet ja algoritmit Uusinta- ja erilliskoe ratkaisuja (Jyrki Kivinen)
58131 Tietorakenteet ja algoritmit Uusinta- ja erilliskoe 12.9.2018 ratkaisuja (Jyrki Kivinen) 1. [10 pistettä] Iso-O-merkintä. (a) Pitääkö paikkansa, että n 3 + 5 = O(n 3 )? Ratkaisu: Pitää paikkansa.
LisätiedotITKP102 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ätiedot815338A 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ätiedot2. 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ätiedotPythonin 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ätiedotOhjelmoinnin 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ätiedotDatatähti 2019 loppu
Datatähti 2019 loppu task type time limit memory limit A Summa standard 1.00 s 512 MB B Bittijono standard 1.00 s 512 MB C Auringonlasku standard 1.00 s 512 MB D Binääripuu standard 1.00 s 512 MB E Funktio
LisätiedotA274101 TIETORAKENTEET JA ALGORITMIT
A274101 TIETORAKENTEET JA ALGORITMIT PERUSTIETORAKENTEET LISTA, PINO, JONO, PAKKA ABSTRAKTI TIETOTYYPPI Tietotyyppi on abstrakti, kun se on määritelty (esim. matemaattisesti) ottamatta kantaa varsinaiseen
LisätiedotOperaattoreiden 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ätiedotIDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit
IDL - proseduurit 25. huhtikuuta 2017 Viimeksi käsiteltiin IDL:n interaktiivista käyttöä, mutta tämä on hyvin kömpelöä monimutkaisempia asioita tehtäessä. IDL:llä on mahdollista tehdä ns. proseduuri-tiedostoja,
LisätiedotSystem.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ätiedotATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014
18. syyskuuta 2014 IDL - proseduurit Viimeksi käsiteltiin IDL:n interaktiivista käyttöä, mutta tämä on hyvin kömpelöä monimutkaisempia asioita tehtäessä. IDL:llä on mahdollista tehdä ns. proseduuri-tiedostoja,
Lisätiedot815338A 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ätiedotAlgoritmit 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ätiedotKääreluokat (oppikirjan luku 9.4) (Wrapper-classes)
Kääreluokat (oppikirjan luku 9.4) (Wrapper-classes) Kääreluokista Javan alkeistietotyypit ja vastaavat kääreluokat Autoboxing Integer-luokka Double-luokka Kääreluokista Alkeistietotyyppiset muuttujat (esimerkiksi
LisätiedotAlgoritmi on periaatteellisella tasolla seuraava:
Algoritmi on periaatteellisella tasolla seuraava: Dijkstra(V, E, l, v 0 ): S := { v 0 } D[v 0 ] := 0 for v V S do D[v] := l(v 0, v) end for while S V do valitse v V S jolle D[v] on minimaalinen S := S
LisätiedotSystem.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ätiedot7.4 Sormenjälkitekniikka
7.4 Sormenjälkitekniikka Tarkastellaan ensimmäisenä esimerkkinä pitkien merkkijonojen vertailua. Ongelma: Ajatellaan, että kaksi n-bittistä (n 1) tiedostoa x ja y sijaitsee eri tietokoneilla. Halutaan
LisätiedotSekalaiset tehtävät, 11. syyskuuta 2005, sivu 1 / 13. Tehtäviä
Sekalaiset tehtävät, 11. syyskuuta 005, sivu 1 / 13 Tehtäviä Tehtävä 1. Johda toiseen asteen yhtälön ax + bx + c = 0, a 0 ratkaisukaava. Tehtävä. Määrittele joukon A R pienin yläraja sup A ja suurin alaraja
LisätiedotMatematiikan tukikurssi, kurssikerta 2
Matematiikan tukikurssi kurssikerta 1 Relaatioista Oletetaan kaksi alkiota a ja b. Näistä kumpikin kuuluu johonkin tiettyyn joukkoon mahdollisesti ne kuuluvat eri joukkoihin; merkitään a A ja b B. Voidaan
Lisätiedot1.3 Lohkorakenne muodostetaan käyttämällä a) puolipistettä b) aaltosulkeita c) BEGIN ja END lausekkeita d) sisennystä
OULUN YLIOPISTO Tietojenkäsittelytieteiden laitos Johdatus ohjelmointiin 811122P (5 op.) 12.12.2005 Ohjelmointikieli on Java. Tentissä saa olla materiaali mukana. Tenttitulokset julkaistaan aikaisintaan
Lisätiedot