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

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

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

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Taas laskin. TIES341 Funktio ohjelmointi 2 Kevät 2006

Ydin-Haskell Tiivismoniste

5.3 Laskimen muunnelmia 5.3. LASKIMEN MUUNNELMIA 57

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

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIEA341 Funktio-ohjelmointi 1, kevät 2008

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

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

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

5.5 Jäsenninkombinaattoreista

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Lisää laskentoa. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Haskell ohjelmointikielen tyyppijärjestelmä

Abstraktit tietotyypit. TIEA341 Funktio ohjelmointi 1 Syksy 2005

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Luku 3. Listankäsittelyä. 3.1 Listat

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

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

Laiska laskenta, korekursio ja äärettömyys. TIEA341 Funktio ohjelmointi Syksy 2005

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

TIEA341 Funktio-ohjelmointi 1, kevät 2008

ITKP102 Ohjelmointi 1 (6 op)

Java-kielen perusteet

14.1 Rekursio tyypitetyssä lambda-kielessä

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

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

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIES542 kevät 2009 Rekursiiviset tyypit

Java-kielen perusteet

Ohjelmoinnin perusteet Y Python

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

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

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

811120P Diskreetit rakenteet

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

7. Näytölle tulostaminen 7.1

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

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

Kerta 2. Kerta 2 Kerta 3 Kerta 4 Kerta Toteuta Pythonilla seuraava ohjelma:

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

Kielioppia: toisin kuin Javassa

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

TIES542 kevät 2009 Tyyppijärjestelmän laajennoksia

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

Ohjelmointiharjoituksia Arduino-ympäristössä

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

Ohjelmoinnin peruskurssien laaja oppimäärä

Yksinkertaiset tyypit

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

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

Luku 2. Ohjelmointi laskentana. 2.1 Laskento

Opiskelijan pikaopas STACK-tehtäviin. Lassi Korhonen, Oulun yliopisto

815338A Ohjelmointikielten periaatteet Harjoitus 4 vastaukset

Java-kielen perusteita

1. Universaaleja laskennan malleja

Ohjelmoinnin peruskurssien laaja oppimäärä

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

Jäsennys. TIEA341 Funktio ohjelmointi 1 Syksy 2005

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

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

Staattinen tyyppijärjestelmä

Ohjelmoinnin peruskurssien laaja oppimäärä

on rekursiivisesti numeroituva, mutta ei rekursiivinen.

Datatähti 2019 alku. task type time limit memory limit. A Kolikot standard 1.00 s 512 MB. B Leimasin standard 1.00 s 512 MB

12 Mallit (Templates)

15. Ohjelmoinnin tekniikkaa 15.1

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

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

TIEA341 Funktio-ohjelmointi 1, kevät 2008

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

Ohjelmointi 1 Taulukot ja merkkijonot

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen

14. Hyvä ohjelmointitapa 14.1

815338A Ohjelmointikielten periaatteet Harjoitus 7 Vastaukset

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

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

S BAB ABA A aas bba B bbs c

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

ELM GROUP 04. Teemu Laakso Henrik Talarmo

Groovy. Niko Jäntti Jesper Haapalinna Group 31

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

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

FORMAALI SYSTEEMI (in Nutshell): aakkosto: alkeismerkkien joukko kieliopin määräämä syntaksi: sallittujen merkkijonojen rakenne, formaali kuvaus

M = (Q, Σ, Γ, δ, q 0, q acc, q rej )

Javan perusteita. Janne Käki

1. Omat operaatiot 1.1

ITKP102 Ohjelmointi 1 (6 op)

1 Raja-arvo. 1.1 Raja-arvon määritelmä. Raja-arvo 1

T Syksy 2006 Tietojenkäsittelyteorian perusteet T Harjoitus 7 Demonstraatiotehtävien ratkaisut

Ohjelmoinnin peruskurssien laaja oppimäärä

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

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

Funktionimien kuormitus. TIES341 Funktio ohjelmointi 2 Kevät 2006

Ohjelmoinnin perusteet Y Python

Transkriptio:

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 ->. Nuoli assosioi oikealle, joten A B C tarkoittaa A (B C). Jos A on tyyppikoostin ja Γ 1,..., Γ n ovat tyyppilausekkeita, niin A Γ 1... Γ n on tyyppilauseke. Tyyppilausekkeidenkin rakenne ilmaistaan sulutuksella tavanomaiseen tapaan. Tyypit voivat olla monomorfisia tai polymorfisia. Polymorfisia ne ovat silloin, kun niissä esiintyy yksikin tyyppimuuttuja, monomorfisia muulloin. Monomorfiset tyypit ovat samoja, jos niillä on sama rakenne (samat tyyppikoostimet ja nuolet samoissa paikoissa). Polymorfiset tyypit (tai monomorfinen tyyppi ja polymorfinen tyyppi) voidaan samastaa, jos kumpikin voidaan muuttaa monomorfiseksi korvaamalla siinä esiintyvät tyyppimuuttujat tyyppilausekkeilla ja jos niistä tulee näin samat. Lausekkeen tyyppi on pääteltävä ja tarkastettava ennen kuin mitään redusointia tehdään. Tämä tapahtuu seuraavien sääntöjen avulla lukemalla lauseketta sisältä ulospäin: Lausekkeen e :: t tyyppi on t. Jos e:n tyyppi ei ole t, on tapahtunut tyyppivirhe ja lauseke hylätään. Lausekkeen tyyppi on α. Lausekkeen () tyyppi on (). Muuttujan tyyppi on α ellei sitä ole kontekstissa muuksi määrätty. Operaattorin, koostimen ja koostinoperaattorin tyyppi riippuu sen määritelmästä. Jos sitä ei ole määritelty, kyseessä on tyyppivirhe ja lauseke hylätään. Literaalin tyyppi riippuu literaalista (tässä vaiheessa voidaan olettaa kokonaislukujen tyypiksi Integer, liukulukujen tyypiksi Double ja merkkijonojen tyypiksi String). Olkoon lausekkeen e tyyppi u, ja olkoon siinä esiintyvän muuttujan x tyyppi t (päätelty e:tä tutkimalla). Tällöin abstraktion λx e tyyppi on t u. Lausekkeessa f e, missä e:n tyyppi on t, tulee f:n tyypin olla t u, missä u on jokin tyyppi (jos näin ei ole, kyseessä on tyyppivirhe ja lauseke hylätään). Tällöin lausekkeen f e tyyppi on u. Lausekkeessa e e, missä e:n tyyppi on t ja e :n tyyppi on t, tulee :n tyypin olla t t u, missä u on jokin tyyppi (jos näin ei ole, kyseessä on tyyppivirhe ja lauseke hylätään). Tällöin lausekkeen f e tyyppi on e e.

20 LUKU 2. OHJELMOINTI LASKENTANA Olkoon lausekkeessa let {x 1 = e 1 ; x 2 = e 2 ;... ; x n = e n } in e 0 lausekkeiden e i tyyppi t i. Tällöin e 0 :n tyypin tulee olla t 0, kun tämä tyyppi päätellään kontekstissa, jossa x i :n tyyppi on t i. Lausekkessa case e of{p 1 q 1,1 e 1,1 q 1,k1 e 1,k1 ;...... ; p n q n,1 e n,1 q n,kn e n,kn } jokaisen p i :n tulee sopia johonkin e:n tyyppiä olevaan lausekkeeseen; jokaisen q i,j :n tyypin tulee olla Bool, kun se tarkastetaan kontekstissa, jossa p i :ssä esiintyvillä muuttujilla on ne tyypit, mitkä niille e:n tyypin mukaan kuuluu; ja jokaisen e i,j tyypin tulee olla sama (olkoon tämä tyyppi u), kun se tarkastetaan kontekstissa, jossa p i :ssä esiintyvillä muuttujilla on ne tyypit, mitkä niille e:n tyypin mukaan kuuluu. Tällöin kyseisen lausekkeen tyyppi on u. Esimerkki 11 Tyypitetään muutama lauseke (merkitään :: :llä tyypitystä): 1. λx x :: α α 2. λx 0 :: α Integer 3. 2 + 2 :: Integer 4. λx x + 0 :: Integer Integer (Tähän tulee myöhemmin muutos.) 5. ( let f = \ x -> case x of _ x == 0 -> 1 x > 0 -> x * f (x - 1) in f ) :: Integer -> Integer Algebralliset tyypit Ydin-Haskellin (melkein) kaikki tyypit määritellään algebrallisina tyyppeinä. Niille ominaista on se, että niiden määrittely muistuttaa kovasti tyyppiin kuuluvien lausekkeiden abstraktia syntaksia. Yksinkertainen algebrallinen tyyppi määritellään seuraavasti: data Bool = True False Tämä määrittelee yhden tyyppikoostimen, Bool, joka toimii sellaisenaan tämän tyypin nimenä, sekä kaksi (tieto)koostinta, True ja False. Tämän määritelmän

2.5. YDIN-HASKELL 21 jälkeen seuraavat tyypitykset pätevät: True :: Bool False :: Bool Vastaavalla tavalla voidaan määritellä muita luettelotyyppejä. Periaatteessa kaikki Ydin-Haskellin perustyypit (triviaalityyppiä () lukuunottamatta) määritellään näin luettelelmalla, joten voidaan ajatella, että on annettu seuraavanlaisia määritelmiä: data Integer = 3 2 1 0 1 2 3 data Char = A B C D Näin asiat eivät tietenkään käytännössä ole (nämä tyypit määritellään käytännössä kielen osana), mutta näin ajatteleminen on hyödyllistä. Myös säiliöitä voidaan määritellä antamalla koostimille parametrityyppejä. data Maybe α = Just α Nothing Tyyppikoostin Maybe on kiinnostava useallakin tavalla. Ensinnäkään se ei ole sinänsä tyypin nimi, vaan sille pitää antaa jokin tyyppi parametriksi (α). Maybe α on geneerinen eli (geneerisesti) polymorfinen tyyppi: se voidaan erikoistaa (specialize) sisältämään jotain toista tyyppiä olevaa dataa antamalla tyyppikoostimelle Maybe tyyppiparametri (esimerkiksi Maybe Bool. Edellä annetusta Maybe α -tyypin määritelmästä seuraavat seuraavat tyypitykset: Nothing :: Maybe α Just :: α Maybe α Tyypin Maybe Bool lausekkeet ovat seuraavat: Nothing Just True Juat False Huomaa, kuinka tyypin määrittely toimii (abstraktina) kielioppina näille lausekkeille! Maybe on hyödyllinen esimerkiksi silloin, kun funktio ei pysty kaikista argumenteistaan antamaan hyödyllistä tulosta. Esimerkiksi:

22 LUKU 2. OHJELMOINTI LASKENTANA ( let f = \ x -> case x of _ x == 0 -> Just 1 x > 0 -> case f (x - 1) of Just x -> Just (x * x ) Nothing -> Nothing x < 0 -> Nothing in f ) :: Integer -> Maybe Integer Kuten kieliopit yleensäkin, myös algebralliset tietotyypit voivat olla rekursiivisia: data List α = Cons α (List α) Nil Tyypin List Bool lausekkeita ovat esimerkiksi seuraavat: Nil Cons True Nil Cons False Nil Cons True (Cons True Nil) Cons True (Cons False Nil) Cons False (Cons True Nil) Cons False (Cons False Nil) Lista on tosin funktio-ohjelmoinnissa niin yleinen käsite, että sitä varten on olemassa ihan oma erityissyntaksinsa, jonka seuraava (kuvainnollinen) määritelmä on seuraava: data [α] = α : [α] [] 2.6 Tietokone laskimena Funktio-ohjelmoijan tietokone on laskin tavallista tasku- tai pöytälaskinta parempi toki, mutta silti laskin. Poikkeuksetta jokainen funktio-ohjelmointijärjestelmä sisältää interaktiivisen osan, johon koneen käyttäjä (on kyse sitten paljon puhutusta loppukäyttäjästä tai ohjelmoijasta) voi käskeä konetta laskemaan jonkin laskun. Funktio-ohjelmointi on pohjimmiltaan sitä, että ohjelmoija kirjoittaa tiedostoon funktioiden ja tyyppien määrittelyä, jolloin hän laajentaa tämän funktiolaskimen laskentakeinoja. Laskimelle voidaan syöttää mikä tahansa kelvollinen lauseke, joissa näitä määritelmiä on käytetty.

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: _ / _ \ /\ /\/ (_) / /_\// /_/ / / GHC Interactive, version 6.0.1, for Haskell 98. / /_\\/ / / http://www.haskell.org/ghc/ \ /\/ /_/\ / _ Type :? for help. Loading package base... linking... done. Prelude> (let { f = \ x -> case x of _ x == 0 -> Just 1 x > 0 -> case f (x - 1) of { Just x -> Just (x*x ) ; Nothing -> Nothing } x < 0 -> Nothing } in f) 5 Just 120 Prelude> (let { f = \ x -> case x of _ x == 0 -> Just 1 x > 0 -> case f (x - 1) of { Just x -> Just (x*x ) ; Nothing -> Nothing } x < 0 -> Nothing } in f) (-3) Nothing Laajennetaan vielä Ydin-Haskellia ymmärtämään vakiomäärittelyt. Määrittely on muotoa vakionnimi :: Tyyppilauseke vakionnimi = lauseke Tyypinmäärittelyrivi ei ole pakollinen, mutta se on suositeltava. Funktiovakioita voidaan määritellä myös siten, että vakionnimen ja yhtäsuuruusmerkin väliin kirjoitetaan yksi tai useampi muuttuja: vakionnimi :: Tyyppilauseke vakionnimi x y z = lauseke Tämä tarkoittaa (oleellisesti) samaa kuin vakionnimi :: Tyyppilauseke vakionnimi = λx λy λz lauseke Määrittelyt (sekä vakioiden että tyyppien) sijoitetaan tiedostoon, jonka nimi alkaa isolla alkukirjaimella ja päättyy päätteeseen.hs ja jonka ensimmäinen rivi kuuluu Module Nimi where, missä Nimi on tiedoston nimi ilman.hs-päätettä. Tiedostossa jokainen määrittely alkaa rivin vasemmasta laidasta (jatkorivit noudattavat aiemmin esitettyä sisennyskäytäntöä). Esimerkiksi voidaan tehdä seuraavanlainen Fibo.hs: module Fibo where fibo :: Integer -> Maybe Integer

24 LUKU 2. OHJELMOINTI LASKENTANA fibo n = case n of _ n < 0 -> Nothing n == 0 -> Just 1 n > 0 -> case fibo (n - 1) of Just m -> Just (n * m) Nothing -> Nothing jonka jälkeen voidaankin käynnistää GHCi komennolla ghci Fibo: _ / _ \ /\ /\/ (_) / /_\// /_/ / / GHC Interactive, version 6.0.1, for Haskell 98. / /_\\/ / / http://www.haskell.org/ghc/ \ /\/ /_/\ / _ Type :? for help. Loading package base... linking... done. Compiling Fibo ( Fibo.hs, interpreted ) Ok, modules loaded: Fibo. *Fibo> fibo 5 Just 120 *Fibo>