Opgave 5 Equationeel programmeren
|
|
|
- Cornelia Smeets
- 10 jaren geleden
- Aantal bezoeken:
Transcriptie
1 Opgave 5 Equationeel programmeren Haskell, Monads en Monadïsch parsen Atze van der Ploeg, Jörg Endrullis December 1, Inleiding Haskell We gaan nu programmeren in de puur functionele taal Haskell. We gebruiken hiervoor de Glasgow Haskell Compiler, de populairste compiler/interpreter voor Haskell. 1.1 ghc en ghci Source code files voor Haskell hebben de extentie.hs Om de intepreter op te starten tik je : ghci Om gelijk de functies die in een Haskell file hebt geschreven te laden e je: ghci <file> De interpreter lijkt een beetje op die van ocaml, maar nu heb je wel lineediting. Enkele belangrijke comman s voor de interpreter zijn: :t <expressie> print het type van expressie. :r herlaad de file die je meegegeven hebt aan ghci. Om een Haskell programma te compileren e je: ghc <file> -o <naam van executable> De file moet dan een functie main hebben, dat is het beginpunt van het programma. Om ervoor te zorgen dat ghc gelijk ook alle files die je importeert compileert e je: ghc --make <file> -o <naam van executable> 1
2 1.2 Syntactische verschillen met ocaml De taal Haskell lijkt op het eerste gezicht een beetje op ocaml, maar met wat kleine syntactische verschillen: In plaats van ; als scheidingsteken in lijsten schrijven we in Haskell,. Dus bijvoorbeeld de lijst: [ 1, 3, 5, 9] In ocaml beginnen typenamen zoals int met een kleine letter, in Haskell beginnen ze met een grote letter, dus bijvoorbeeld Int. De : betekent in ocaml heeft het type van, hiervoor gebruiken we in Haskell :: In ocaml schrijven we dus bijvoorbeeld: 1 : int In Haskell schrijven we: 1 :: Int In ocaml schrijven we de Cons operator voor lijsten als ::, in Haskell schrijven we :. In ocaml schrijven we dus bijvoorbeeld: 1::[3;5;6] In Haskell schrijven we: 1:[3,5,6] In plaats van match... with schrijven we in Haskell case... of: In ocaml schrijven we dus bijvoorbeeld: match lijst with [] -> 0 h::t -> 1 In Haskell schrijven we: case lijst of [] > 0 h:t > 1 In Haskell schrijven we geen rec voor recursieve functies, de compiler zoekt zelf uit of een functie recursief is. Als we een top-level functie in Haskell defineren schrijven we er geen let voor. In ocaml schrijven we dus bijvoorbeeld: 2
3 let plus x y = x + y In Haskell schrijven we: plus x y = x + y Als we in de interpreter een functie willen definiëren schrijven we er wel let voor. Als we in Haskell meerdere let expressies na elkaar en dan schrijven maar 1 keer let en maar 1 keer in. In ocaml schrijven we dus bijvoorbeeld: let telkwadratenop x y = let xkwadraat = x * x in let ykwadraat = y * y in xkwadraat + ykwadraat In Haskell schrijven we: telkwadratenop x y = let xkwadraat = x * x ykwadraat = y * y in xkwadraat + ykwadraat Waar we in ocaml fun x -> fun y -> fun z -> expressie schrijven, schrijven we in Haskell (\x y z -> expressie. De \ betekent hier een λ. Dit is overigens dezelfde notatie als in lambdamonkey. In Haskell kunnen we naast let ook where gebruiken. We kunnen het vorige voorbeeld bijvoorbeeld ook zo opschrijven: telkwadratenop x y = xkwadraat + ykwadraat where xkwadraat = x * x ykwadraat = y * y Let wel op dat where alleen maar in functies met namen werkt, we kunnen dus bijvoorbeeld niet schrijven: (\x y > x + y where xkwadraat = x * x ykwadraat = y * y In Haskell is whitespace ook code. In de meeste programmeertalen, zoals bijvoorbeeld Java en OCaml, maakt hoever je insprint en waar je newlines zet niet uit. Bijvoorbeeld het volgende Java programmatje: 3
4 class Test{ public static void main(string[] argv{ if (true then { System.out.printf("Waar"; } else { System.out.printf("Niet waar"; } } } Hadden we in Java ook zonder whitespace kunnen schrijven: class Test{public static void main(string[] argv{if(truethen{system.out. printf("waar";}else{system.out.printf("niet waar";}}} In Haskell maakt het wel uit hoe ver je inspringt en of je een newline ergens zet. Bijvoorbeeld het volgende stukje Haskell code: isempty list = case list of [] > True h:t > False Dat kunnen we niet zonder whitespace schrijven zoals in Java. De Haskell compiler ziet namelijk waar het volgende case-geval begint or de newline. Het is belangrijk dat je voor het inspringen niet tab-tekens en spaties or elkaar gebruikt. Als we het vorige stukje Haskell code dus bijvoorbeeld als volgt opschrijven: isempty list = case list of [] > True <tab>h:t > False Dan ziet het er in je editor goed uit als de editor 4 spaties voor een tab laat zien. Als je editor een tab als 2 spaties laat zien, dan krijg je dit: isempty list = case list of [] > True h:t > False Dit gaat dus fout: De Haskell compiler weet immers niet hoeveel spaties een tab-teken betekent, dat is afhankelijk van de editor. De makkelijkste manier om hier mee om te gaan is om je editor zo in te stellen dat hij als je op tab drukt bijvoorbeeld 4 spaties in de file zet in plaats van een tab teken. De Haskell compiler kan je waarschuwen als er tabs in je source file staat or het argument -fwarn-tabs aan ghc of ghci mee te geven. Dus bijvoorbeeld: 4
5 ghci -fwarn-tabs <jouw file> In Haskell begint een commentaar van 1 regel met --, dit is hetzelfde als // in java. Commentaar van meerdere regels begint met {- en eindigt met -}, dit is hetzelfde als /*... */ in java. In Haskell kunnen we aan pattern-matching en. Dat wil zeggen dat we bijvoorbeeld kunnen schrijven: somlijst [] = 0 somlijst (eerste:rest = eerste + (somlijst rest De eerste definitie wordt gebruik als de lijst van de vorm [] is. Als de lijst van de vorm (eerst:rest is dan wordt de tweede definitie gebruikt. Het bovenstaande stukje code is dus hetzelfde als: somlijst lijst = case lijst of [] > 0 (eerste:rest > eerste+(somlijst rest Als we bijvoorbeeld de definitie van een functie nulnaareen zo hebben opgeschreven: nulnaareen 0 = 1 nulnaareen x = x Als we dan nulnaareen 0 opschrijven dan zijn dus alle twee de definities van nulnaareen mogelijk. Haskell zal dan altijd de eerste pakken. Dus de uitkomst van nulnaareen 0 is 1. Dus als we het andersom opschrijven: nulnaareen x = x nulnaareen 0 = 1 Dan is de uitkomst van nulnaareen 0 dus 0. In Haskell schrijven we type declaraties iets anders op. Bijvoorbeeld in ocaml: type a tree = leaf of a node of tree * int * tree In haskell schrijven we: data Tree a = Leaf a Node Tree a Tree Een voorbeeldje waar we de bovenstaande verschillen zien: In ocaml schrijven we: 5
6 let telaantalvoorkomensinlijst element lijst : int->list of int->int= let hulpfunctie lijst aantalvoorkomens = match lijst with [] -> aantalvoorkomens h::t -> let plusaantalvoorkomens = if h == element then then 1 else 0 in let nieuweaantalvoorkomens = aantalvoorkomens + plusaantalvoorkomens in let resultaat = hulpfunctie t nieuweaantalvoorkomens in resultaat in hulpfunctie lijst 0 aantal1en = telaantalvoorkomensinlijst 1 [1;2;3;1;65;2] In Haskell schrijven we: telaantalvoorkomensinlijst :: Int >[Int] >Int telaantalvoorkomensinlijst element lijst = hulpfunctie lijst 0 where hulpfunctie [] aantalvoorkomens = aantalvoorkomens hulpfunctie (h:t aantalvoorkomens = let plusaantalvoorkomens = if h == element then 1 else 0 nieuweaantalvoorkomens = aantalvoorkomens + plusaantalvoorkomens resultaat = hulpfunctie t nieuweaantalvoorkomens in resultaat aantal1en = telaantalvoorkomensinlijst 1 [1,2,3,1,65,2] Opgave 1 Schrijf nu de volgende functies in Haskell: lengte, die de lengte van een lijst van geeft. (Deze functie heet length in de standaard library van Haskell append, die twee lijsten achter elkaar plakt. (Deze functie heet (++ in de standaard library van Haskell 6
7 pastoeopelkelement die als input neemt: Een functie met 1 argument Een lijst En die als output de lijst geeft waarbij op elk element die functie is toegepast. Dus de uitkomst van bijvoorbeeld pastoeopelkelement (\x -> x + 2 [2,3,1] moet [4,5,3] zijn. (Deze functie heet map in de standaard library van Haskell verwijderals, die als input neemt: Een functie met 1 argument met als resultaat een Bool. Een lijst En die als output de lijst teruggeeft waar elk element waarbij de functie True opleverde er uit gehaald is. De uitkomst van bijvoorbeeld verwijderals (\x -> x > 5 [10,4,2,6,0] moet dan dus [4,2,0] zijn. neem, de een getal n en een lijst neemt, en een lijst met de eerste n elementen van de lijst teruggeeft. (Deze functie heet take in de standaard library van Haskell Het is hierbij niet toegestaan om de functies length,++,map en take te gebruiken. Zet je functies in een file IntroHaskell.hs. Het grote verschil tussen Haskell en ocaml is dat ocaml een strict (eager taal is en Haskell een lazy taal is. Dat wil zeggen dat ocaml de call by value reductie strategie gebruikt en Haskell de lazy reductie strategie (dit lijkt op call by need. De call by value en call by need reductie strategieën worden uitgelegd in hoofdstuk twee van het dictaat over lambda calculus. Praktisch gezien betekent het dat als we bijvoorbeeld de volgende functie aanroep hebben: telkwadratenop ( * 60 (300^2 Een stricte taal zou dan eerst de twee argumenten ( * 60 (300^2 helemaal uitrekenen en dan de functie telkwadratenop uitvoeren met de berekende argumenten. Dit is overgens ook de manier waarop het in alle imperatieve talen, zoals java, werkt. Een lazy taal onthoudt hoe het de argumenten kan berekenen, maar berekent de argumenten zelf niet, de uitkomst van de argumenten wordt pas berekent als de uitkomsten echt nodig zijn. Een lazy taal is dus lui : het berekent pas iets als het echt niet anders kan. Stel we hebben de functie gooiargumentenw eg gooiargumentenweg x y = 1 Als we dan de volgende functie aanroep hebben: 7
8 gooiargumentenweg (faculteit 210 (60^(60^(60^120 Dan zou een stricte taal proberen de argumenten uit te rekenen (wat ontzettend lang duurt en dan de functie gooiargumentenw eg aanroepen. De argumenten worden dus uitgerekend, maar dat was helemaal niet nodig. Een lazy taal zou alleen maar onthouden hoe hij de argumenten kan uitrekenen, mocht dat nodig zijn, en dat de functie gooiargumentenw eg aanroepen, er wordt dus niks onnodig uitgerekend. Hieror kunnen we in Haskell ook met oneindige structuren rekenen, zoals bijvoorbeeld oneindige lijsten. De oneindige lijst met alleen maar 1en kunnen we bijvoorbeeld zo definiëren: oneindigveel1en = 1:oneindigVeel1en Nu kunnen we bijvoorbeeld het eerste getal van die lijst opvragen: head oneindigveel1en Een stricte taal zou nu proberen eerst de gehele lijst met oneindig veel 1en uit te rekenen en dan pas de functie head aanroepen. Een lazy taal zoals Haskell onthoud enkel hoe hij die lijst moet berekenen, en roept dan head aan. De functie head heeft dan het eerste van de lijst nodig, dus berekenen we net zo lang in de lijst (en niet langer todat we weten wat het eerste element is. We kunnen bijvoorbeeld ook de eerste 100 elementen van de oneindige lijst van 1en opvragen. neem 100 oneindigveel1en Opgave 2 Schrijf nu de volgende dingen in Haskell: De oneindige lijst 1, 2, 3, 4, 5,... De oneindige lijst 0, 1, 0, 1, 0, 1, 0, 1,... De oneindige lijst van alle 3-vouden. De oneindige lijst van alle positieve getallen, behalve alle drievouden (hint: Gebruik verwijderals en mod. Een functie allenvouden, die een getal n als input neemt en de oneindige lijst van alle n vouden teruggeeft. Een functie allesbehalveallenvouden, die een getal n als input neemt en de oneindige lijst van alle positieve getallen behalve alle n vouden teruggeeft. Een functie zonderallenvouden, die een getal n neem en een lijst van getallen en die de lijst zonder alle n vouden teruggeeft. 8
9 Zet je functies in de file IntroHaskell.hs. Bij het vak datastructuren en algoritmen heb je al kennis gemaakt met de zeef van Eratosthenes, een algoritme om priemgetallen te berekenen. We gaan nu dit algoritme gebruiken om in Haskell de lijst van alle priemgetallen te maken. De zeef van Eratosthenes werkt als volgt: 1. We beginnen met de oneindige lijst 2, 3, 4, 5, 6, 7, We pakken het eerste getal uit de lijst, dat is een priemgetal, en halen alle veelvouden van dat getal weg uit de rest van de lijst. 3. We en weer stap 2 met de rest van de lijst. Opgave 3 Programmeer nu de oneindige lijst van priemgetallen. Zet je functie in de file IntroHaskell.hs. 2 Monads Met monads kun je sommige dingen handiger en leesbaarder opschrijven in een puur functionele taal. In dit gedeelte leggen we uit hoe dat werkt. We beginnen met het voorbeeld MisschienEen. 2.1 MisschienEen Bij sommige functies komt uit de functie misschien een resultaat. Voorbeelden van dit soort functies zijn: De functie gedeelddoor die als input neemt Een getal, genoemd de teller. Een getal, genoemd de noemer en als output geeft: De teller gedeeld or de noemer. Als de noemer nul is dan het resultaat dus iets van de vorm x 0 en dus is de uitkomst geen nummer. Dus deze functie heeft misschien geen resultaat. Een functie indexv an die als input neemt: Een lijst van verschillende getallen Een getal en als output geeft: 9
10 De index van dat getal in de lijst. Als het getal niet in de lijst voorkomt dan heeft het natuurlijk geen index. Dan hebben we dus geen resultaat. De functie restantstring die als input neemt: Een string, genoemd x Nog een string, genoemd y en als output geeft: De string y waarbij de karakters uit x aan het begin zijn weggehaald. Als de string y niet begint met de string x, dan is er geen resultaat. 2.2 Het MisschienEen type In Haskell kunnen we een type definiëren voor de output van dit soort functies: 1 data MisschienEen resultaattype = GeenResultaat Resultaat resultaattype hetzelfde type in Ocaml zou zijn: type resultaattype misschieneen = GeenResultaat Resultaat of resultaattype Nu kunnen we de bovenstaande voorbeelden in Haskell opschrijven: gedeelddoor :: Double >Double >MisschienEen Double gedeelddoor teller noemer = if noemer == 0 then GeenResultaat else Resultaat (teller / noemer indexvan :: [Int] >Int >MisschienEen Int indexvan lijst getal = indexvanhulp lijst 0 where indexvanhulp lijst index = case lijst of [] > GeenResultaat eerstegetal:restlijst > if eerstegetal == getal then Resultaat index else indexvanhulp restlijst (n+1 1 Dit type is al gedefiniëerd in de standaard library van Haskell, daar heet het Maybe. 10
11 Opgave 4 Programmeer zelf de functie restantstring in Haskell. string een lijst van karakters (chars. In Haskell is een Voeg je functie toe aan file MisschienEen.hs waarin het MisschienEen type en de voorbeelden staan. 2.3 Infix functies In Haskell kunnen we een functie met twee argumenten ook infix maken, zoals +,-,*,/, dus met de naam van de functie tussen de twee argumenten. Een infix functie noemen we meestal een operator We maken nu een operator van gedeelddoor : teller // noemer = gedeelddoor teller noemer In plaats van gedeelddoor 3 2 kunnen we nu dus 3 // 2 schrijven. Als voorbeeld van het gebruik van de // operator gaan we nu de volgende functie implementeren: f(x, y, z = Deze functie levert natuurlijk geen resultaat als y == 0 of z == 0. We programmeren dit als volgt: f :: Double >Double >Double >MisschienEen Double f x y z = case x // y of GeenResultaat > GeenResultaat Resultaat xgedeelddoory > case xgedeelddoory // z of GeenResultaat > GeenResultaat Resultaat resultaat > Resultaat resultaat Dus als x // y geen resultaat heeft, dan heeft de hele functie geen resultaat. En als xgedeelddoory // z geen resultaat heeft dan ook niet. Aangezien xgedeelddoory // z zelf al iets van type MisschienEen Double oplevert kunnen we het natuurlijk ook als volgt opschrijven: fkorter :: Double >Double >Double >MisschienEen Double fkorter x y z = case x // y of x y z 11
12 GeenResultaat > GeenResultaat Resultaat xgedeelddoory > xgedeelddoory // z Als iets ingewikkelder voorbeeldje van het gebruik van // nemen we de functie : Dit implementeren we als volgt: g(x, y, z, s = y s + z s x y x z g :: Double >Double >Double >Double >MisschienEen Double g x y z s = case x // y of GeenResultaat > GeenResultaat Resultaat xgedeelddoory > case y // z of GeenResultaat > GeenResultaat Resultaat xgedeelddoorz > case y // s of GeenResultaat > GeenResultaat Resultaat ygedeelddoors > case z // s of GeenResultaat > GeenResultaat Resultaat zgedeelddoors > let teller = ygedeelddoors + zgedeelddoors noemer = xgedeelddoory xgedeelddoorz in teller // noemer 2.4 De >>= operator Op deze manier zijn de functies f en g niet goed leesbaar. We herhalen telkens hetzelfde patroon, namelijk : case... of GeenResultaat > GeenResultaat Resultaat... >... We kunnen een operator(infix functie, >>=, voor dit patroon maken: (>>= :: MisschienEen type1 >(type1 >MisschienEen type2 >MisschienEen type2 linkerresultaat >>= rechterfunctie = case linkerresultaat of GeenResultaat > GeenResultaat Resultaat nummer > let resultaat = rechterfunctie nummer in resultaat of dezelfde functie anders opgeschreven met pattern matching: 12
13 (>>= :: MisschienEen type1 >(type1 >MisschienEen type2 >MisschienEen type GeenResultaat >>= rechterfunctie = GeenResultaat (Resultaat nummer >>= rechterfunctie = rechterfunctie nummer Deze functie krijg een linkerresultaat aan linkerkant van de >>= van het type M isschien Double, dus bijvoorbeeld Resultaat 10.0 of GeenResultaat. type1 en type2 in de type declaratie mogen willekeurige types zijn, dus bijvoorbeeld alletwee Double. Aan de rechterkant van de >>= krijgt het een functie die als input 1 Double neemt en iets van type MisschienEen Double output. Bijvoorbeeld de functie : driegedeelddoor x = 3 // x Als het linkerresultaat GeenResultaat is, dan is de uitkomst van de hele functie GeenResultaat en wordt de rechterfunctie helemaal niet gebruikt. Als het van de vorm Resultaat nummer is dan wordt dan nummer als input gegeven aan de rechterfunctie en is het resultaat van de hele functie het resultaat van de rechterf unctienummer. gedeelddoor3 x = x // 3 Deze operator >>= kunnen we nu gebruiken om f handiger op te schrijven: fbeter :: Double >Double >Double >MisschienEen Double fbeter x y z = (x // y >>= gedeelddoorz where gedeelddoorz xgedeelddoory = xgedeelddoory // z In plaats van gedeelddoorz kunnen we natuurlijk ook een anonieme (lambda functie gebruiken: fbeterlambda :: Double >Double >Double >MisschienEen Double fbeterlambda x y z = (x // y >>= (\xgedeelddoory > xgedeelddoory // z We kunnen g nu als volgt op schrijven: gbeter :: Double >Double >Double >Double >(MisschienEen Double gbeter x y z s = (x // y >>= (\xgedeelddoory > (x // z >>= 13
14 (\xgedeelddoorz > let noemer = xgedeelddoory xgedeelddoorz in (y // s >>= (\ygedeelddoors > (z // s >>= (\zgedeelddoors > let teller = ygedeelddoors + zgedeelddoors in teller // noemer Merk hierbij op dat als bijvoorbeeld (x // y als uitkomst GeenResultaat heeft, dat dan de rest van de functie niet wordt uitgerekend. 2.5 Do notatie Zo is het nog steeds niet echt leesbaar. Gelukkig heeft Haskell hier een truukje voor: In plaats van : fbeterlambda :: Double >Double >Double >MisschienEen Double fbeterlambda x y z = (x // y >>= (\xgedeelddoory > xgedeelddoory // z kunnen we namelijk schrijven: fnogbeter :: Double >Double >Double >MisschienEen Double fnogbeter x y z = xgedeelddoory < x // y xgedeelddoory // y Hierbij betekent xgedeelddoory <- x // y: Reken x // y uit en als er GeenResultaat uitkomt dan stoppen we met verder rekenen en returnen we GeenResultaat voor de hele functie. Als er Resultaat nummer uitkomt, dan slaan we dat nummer op in de variabele xgedeelddoory en gaan we verder met de rest van de functie. Dus als je een expressie begin met dan vertaalt de Haskell compiler elke expressie van de vorm x < y volgenderegel naar 14
15 y >>= (\x > volgenderegel Dus voor de Haskell compiler zijn fbeter en fnogbeter hetzelfde. Als we een expressie van meerdere regels hebben, bijvoorbeeld: x < y p < z r < l laatsteregel Dan vertaalt de Haskell compiler dit als: y >>= (\x > z >>= (\p > l >>= (\r > laatsteregel 2.6 let in Tussen de operaties waarbij het resultaat een M isschieneen Double is kunnen we ook operaties opschrijven die niet als resultaat een M isschieneen Double hebben. Als we bijvoorbeeld schrijven, merk hierbij op dat als we een let in een block schrijven dat we dan geen in schrijven.: x < y let r = q p < z laatsteregel dan vertaalt de Haskell compiler dit als: y >>= (\x > let r = q in z >>= (\p > laatsteregel Nu kunnen we g als volgt opschrijven: gnogbeter :: Double >Double >Double >Double >(MisschienEen Double gnogbeter x y z s = xgedeelddoory < x // y 15
16 xgedeelddoorz < y // z let noemer = xgedeelddoory xgedeelddoorz ygedeelddoors < y // s zgedeelddoors < z // s let teller = ygedeelddoors + zgedeelddoors teller // noemer Nu is het eindelijk leesbaar. 2.7 return Als we bijvoorbeeld hebben geschreven: x < y laatsteregel dan vertaalt de Haskell compiler dit dus als: y >>= (\x > laatsteregel Merk hierbij op dat (\x -> laatsteregel het type Double -> MisschienEen Double heeft en dus een geldig tweede argument voor >>= is, want >>= heeft het type: MisschienEen Double->(Double->MisschienEen Double->(MisschienEen Double. De laatste regel moet dus wel iets van type MisschienEen Double hebben. Bij de voorgaande twee voorbeelden f en g was de laatste regel altijd een operatie met als uitkomst een MisschienEen Double. We gaan nu uitleggen hoe de notatie werkt als dat niet zo is. Als voorbeeld nemen we de volgende functie: p(x, y, z = x y + z x Zonder de notatie kunnen we die als volgt opschrijven: p :: Double >Double >Double >Double >(MisschienEen Double p x y z = (x // y >>= (\xgedeelddoory > (z// x >>= (\zgedeelddoorx > let resultaat = xgedeelddoory + zgedeelddoorx in Resultaat resultaat met de notatie lukt het nog niet: 16
17 p :: Double >Double >Double >Double >(MisschienEen Double p x y z = xgedeelddoory < x // y zgedeelddoorx < z // x let resultaat = xgedeelddoory + zgedeelddoorx? De laatste regel moet immers iets van type M isschieneen Double hebben, en resultaat heeft type Double. We kunnen dit oplossen or te schrijven: pdo :: Double >Double >Double >Double >(MisschienEen Double pdo x y z = xgedeelddoory < x // y zgedeelddoorx < z // x let resultaat = xgedeelddoory + zgedeelddoorx Resultaat resultaat Nu is de laatste regel Resultaat resultaat van het type MisschienEen Double, dus nu werkt het. Om het geheel nog iets leesbaarder te maken definiëren we een functie return return :: Double >MisschienEen Double return waarde = Resultaat waarde dan kunnen we schrijven: pdoreturn :: Double >Double >Double >Double >(MisschienEen Double pdoreturn x y z = xgedeelddoory < x // y zgedeelddoorx < z // x let resultaat = xgedeelddoory + zgedeelddoorx return resultaat We kunnen f en g nu ook nog iets leesbaarder opschrijven: fperfect :: Double >Double >Double >MisschienEen Double fperfect x y z = xgedeelddoory < x // y resultaat < xgedeelddoory // z return resultaat gperfect :: Double >Double >Double >Double >(MisschienEen Double gperfect x y z s = xgedeelddoory < x // y xgedeelddoorz < y // z let noemer = xgedeelddoory xgedeelddoorz ygedeelddoors < y // s 17
18 zgedeelddoors < z // s let teller = ygedeelddoors + zgedeelddoors resultaat < teller // noemer return resultaat Opgave 5 Programmeer zelf de functie: v(x, y, z, s = Op alle drie de manieren. Dus met: x y z s y s case... of GeenResultaat->GeenResultaat Resultaat nummer ->... De >>= functie. De notatie plus return. Voeg je functie toe aan file MisschienEen.hs. ( y s + z x 2.8 If in In de -notatie kunnen we ook if schrijven. Als voorbeeld nemen we de volgende functie: waarin r(x, y, z = p + q p = x y { p < 6 q = p 6 Zonder de notatie zouden we dit schrijven: r :: Double >Double >Double >(MisschienEen Double r x y z = (x // y >>= (\p > let qmisschien = if p < 6 then (y //z else Resultaat z in y z z 18
19 qmisschien >>= (\q > p + q Met de -notatie kunnen we schrijven: r :: Double >Double >Double >(MisschienEen Double r x y z = p < x // y q < if p < 6 then y // z else Resultaat z let resultaat = p + q return resultaat Of r :: Double >Double >Double >(MisschienEen Double r x y z = p < x // y if p < 6 then q < y // z let resultaat = p + q return resultaat else let resultaat = p + z return resultaat Merk bij dit laatste stukje code op dat als je in de body van then en else weer de -notatie wil gebruiken dat je dan weer er voor moet zetten. Merk verder op voor de then en de else een spatie staat. Dit moet als je een if in -notatie schrijft, anders dan snapt de compiler niet wat je beelt. Op exact dezelfde manier kan je ook een case expressie in de notatie gebruiken. Opgave 6 Programmeer zelf de functie: w(x, y, z, s = p + q s waarin p = x y z + s { p > 10 q = p 10 x z z x 19
20 Op alle drie de manieren. Dus met: case... of GeenResultaat->GeenResultaat Resultaat nummer ->... De >>= functie. De notatie plus return en if. Voeg je functie toe aan file MisschienEen.hs. 2.9 Toestand Bij het voorbeeld van MisschienEen hebben we gezien hoe we de >>= en return functies kunnen gebruiken om niet steeds maar case... of GeenResultaat > GeenResultaat Resultaat... >... te schrijven. We gaan nu zien hoe we deze functies kunnen gebruiken om de toestand (state van iets bij te houden. Als voorbeeld van toestand bekijken we het volgende java programmatje: class Coordinaat { int x,y; } Coordinaat(int x,int y{ this.x = x; this.y = y; } void verplaats(int xverplaats, int yverplaats{ x += xverplaats; y += yverplaats; } Elk object van het type Coordinaat heeft een toestand namelijk de plek waarnaar het Coordinaat object verwijst, dus de waarden van de x en y variabelen. De constructor maakt een object en zet hem in zijn begintoestand. Strict gezien kan iets in een puur functionele taal geen toestand hebben. Alles is, met een java-term, immutable. We kunnen wel uit een toestand een nieuwe toestand maken en die de hele tijd or geven. Als voorbeeld hiervan programmeren we het bovenstaande in Haskell: 20
21 data Coordinaat = Coordinaat Int Int verplaats :: Int >Int >Coordinaat >Coordinaat verplaats xverplaats yverplaats (Coordinaat x y = let nieuwex = x + xverplaats nieuwey = y + yverplaats nieuwecoordinaat = Coordinaat nieuwex nieuwey in nieuwecoordinaat We zien hierbij dat we het coordinaat niet veranderen, dat kan immers niet, maar een nieuwe coordinaat maken. Dat nieuwe coordinaat is de nieuwe toestand van het oude coordinaat. Als we iets twee keer willen verplaatsen dan tikken we in java: Coordinaat c = new Coordinaat(0,0; c.verplaats(1,0; c.verplaats(0,1; Als we hetzelfde willen en in haskell dan tikken we: let begintoestand = Coordinaat 0 0 tweedetoestand = verplaats 1 0 begintoestand derdetoestand = verplaats 0 1 tweedetoestand in derdetoestand Dus je geeft de toestand de hele tijd expliciet or. Soms heb je een functie die èn de toestand veranderd en iets teruggeeft. Bijvoorbeeld de volgende java functie verplaatsengaatbuitenbord in de class Coordinaat: static final int BREEDTE = 10, HOOGTE=10; bool verplaatsengaatbuitenbord(int verplaatsx, int verplaatsy{ verplaats(verplaatsx,verplaatsy; return isopbord(; } bool opbord({ return x >= 0 && x < BREEDTE && y >= 0 && y < HOOGTE; } In Haskell moet we dan expliciet de uitkomst en de nieuwe toestand teruggeven: verplaatsengaatbuitenbord :: Int >Int >Coordinaat >(Coordinaat,Bool verplaatsengaatbuitenbord verplaatsx verplaatsy begincoordinaat= let nieuwecoordinaat = verplaats verplaatsx verplaatsy begincoordinaat resultaat = opbord nieuwecoordinaat in (nieuwecoordinaat,resultaat breedte = 10 hoogte = 10 opbord (Coordinaat x y = x >= 0 && x < breedte && y >= 0 && y < hoogte 21
22 We gaan nu zien hoe we dit in Haskell kunnen opschrijven zonder telkens expliciet de toestand or te geven. We en dit met behulp van de >>= en return functies en de -notatie ToestandFunctie Om het geheel leesbaarder te maken introduceren we eerst een andere naam voor Coordinaat, namelijk Toestand: type Toestand = Coordinaat Dit is enkel een andere naam, dus overal waar we in het vervolg Toestand schrijven kunnen we net zo goed Coordinaat schrijven. Een ToestandFunctie is een functie die als input een toestand krijgt en als output de nieuwe toestand en het resultaat van de functie geeft: data ToestandFunctie resultaattype = ToestandsFunctie (Toestand >(Toestand,resultaatType Waarbij resultaattype een willkeurig ander type kan zijn, bij voorbeeld Int of Double. Iets van bijvoorbeeld het type ToestandFunctie Bool is dus een fuctie van het type Toestand->(Toestand,Bool met de constructor ToestandFunctie ervoor. Bijvoorbeeld de functie verplaatsnoordengaatbuitenbordtoestandfunctietf hieronder het heeft type ToestandFunctie Bool: verplaatsnoordengaatbuitenbordtf :: ToestandFunctie Bool verplaatsnoordengaatbuitenbordtf = ToestandFunctie verplaatsnoordengaatbuitenbord verplaatsnoordengaatbuitenbord :: Toestand >(Toestand,Bool verplaatsnoordengaatbuitenbord coordinaat = verplaatsengaatbuitenbord 0 1 coordinaat We zullen hieronder alle achter de namen van alle functies die toestandfuncties zijn TF zetten. Sommige functies zoals verplaats geven geen uitkomst terug. maken we een aparte waarde GeenUitkomst: Daarvoor data GeenUitkomst = GeenUitkomst Nu kunnen we de functies verplaats en opbord als ToestandFunctie opschrijven. verplaatstf:: Int >Int >ToestandFunctie GeenUitkomst verplaatstf xverplaats yverplaats = ToestandFunctie (\(Coordinaat x y > let nieuwex = x + xverplaats nieuwey = y + yverplaats 22
23 nieuwetoestand = Coordinaat nieuwex nieuwey in (nieuwetoestand,geenuitkomst opbordtf :: ToestandFunctie Bool opbordtf = ToestandFunctie (\(Coordinaat x y > let resultaat = x >= 0 && x < breedte && y >= 0 && y < hoogte nietgewijzigdetoestand = (Coordinaat x y in (nietgewijzigdetoestand,resultaat 2.11 etoestandfunctie De functies verplaats en opbord zijn nu ToestandFuncties. bijvoorbeeld niet meer Dus we kunnen opbord (Coordinaat schrijven. Want opbord heeft het type ToestandFunctie Bool en niet Coordinaat->Bool. Om de toestand functies te kunnen uitvoeren definiëren we de functie et oestandf unctie: etoestandfunctie :: ToestandFunctie uitkomsttype >Toestand >(Toestand,uitkomstType etoestandfunctie (ToestandFunctie functie begintoestand = functie begintoestand Dus schrijven we bijvoorbeeld: draaitoestandfunctie opbord (Coordinaat >>= voor ToestandFuncties Nu willen we natuurlijk twee van deze ToestandFuncties achter elkaar kunnen uitvoeren. Dus we willen van twee toestands functies 1 nieuwe toestandfunctie maken, die de twee toestandsfuncties achter elkaar uitvoerd. Daarvoor definiëren we een implementatie van >>= voor toestand functies: (>>= :: ToestandFunctie resultaattype1 >(resultaattype1 >ToestandFunctie resultaattype2 >ToestandFunctie resultaattype2 (ToestandFunctie functielinks >>= (toestandfunctieonthoudresultaatrechts = ToestandFunctie (\begintoestand > let (tweedetoestand,resultaatlinks = functielinks begintoestand (ToestandFunctie functierechts = toestandfunctieonthoudresultaatrechts resultaatlinks (derdetoestand,resultaatrechts = functierechts tweedetoestand in (derdetoestand,resultaatrechts 23
24 Merk hierbij op dat de uitkomst van de nieuwe samengestelde toestand functie de uitkomst van de tweede toestand functie is. De functie verplaatsengaatbuitenbord is een samengestelde functie van verplaats en opbord. Met onze nieuwe >>= implementatie kunnen we dat nu op deze manier op schrijven: verplaatsengaatbuitenbordtf :: Int >Int >ToestandFunctie Bool verplaatsengaatbuitenbordtf xverplaats yverplaats = (verplaatstf xverplaats yverplaats >>= (\geenuitkomst > opbordtf Of in de notatie: verplaatsengaatbuitenbordmetdotf :: Int >Int >ToestandFunctie Bool verplaatsengaatbuitenbordmetdotf xverplaats yverplaats = geenuitkomst < verplaatstf xverplaats yverplaats opbordtf Om de return voor ToestandFuncties te kunnen gebruiken moeten we die eerst definiëren: return :: uitkomsttype > ToestandFunctie uitkomsttype return uitkomst = ToestandFunctie (\toestand > (toestand,uitkomst Dus bijvoorbeeld return True geeft een ToestandsFunctie die de toestand met rust laat en True als uitkomst heeft. Dus bijvoorbeeld x >>= (\uitkomst x -> return True heeft dat precies het resultaat was we willen: Een ToestandFunctie die eerst x uitvoert en vervolgens altijd True als uitkomst heeft. Nu kunnen we dus schrijven: verplaatsengaatbuitenbordbetertf :: Int >Int >ToestandFunctie Bool verplaatsengaatbuitenbordbetertf xverplaats yverplaats = geenuitkomst < verplaatstf xverplaats yverplaats isopbord < opbordtf return isopbord 2.13 De >> operator In deze functie maken we een variabele voor de uitkomst van verplaats xverplaats yverplaats, maar de uitkomst van deze functie is altijd GeenUitkomst. We willen voor deze uitkomst dus eigenlijk helemaal geen variabele maken. Om dit te kunnen en introduceren we de >> operator. 24
25 De >> operator neemt twee ToestandFuncties, voert de eerste uit, gooit zijn resultaat weg, draait de tweede toestand functie en geeft als uitkomst de uitkomst van de tweede ToestandFunctie. (>> :: ToestandFunctie resultaattype1 > ToestandFunctie resultaattype2 > ToestandFunctie resultaattype2 (ToestandFunctie functie1 >> (ToestandFunctie functie2 = ToestandFunctie (\begintoestand > let (tweedetoestand,weggooiresultaat = functie1 begintoestand (derdetoestand, resultaat = functie2 tweedetoestand in (derdetoestand,resultaat Nu kunnen we verplaatsengaatbuitenbord beter opschrijven: verplaatsengaatbuitenbordperfecttf :: Int >Int >ToestandFunctie Bool verplaatsengaatbuitenbordperfecttf xverplaats yverplaats = (verplaatstf xverplaats yverplaats >> opbordtf De -notatie vertaalt je expressie met een >>= als je het resultaat van een regel onthoud, en met een >> als je dat niet et. Dus kunnen we nu in de -notatie opschrijven: verplaatsengaatbuitenbordmetdoperfecttf :: Int >Int >ToestandFunctie Bool verplaatsengaatbuitenbordmetdoperfecttf xverplaats yverplaats = verplaatstf xverplaats yverplaats isopbord < opbordtf return isopbord Een ander voorbeeld hiervan is de functie verplaatsn oordw est die de coordinaat eerst naar het noorden en dan naar het westen verplaatst en als het coordinaat daarna buiten bord is dan zet hij het coordinaat in het midden van het bord (4,4. Het resultaat van de functie is of het coordinaat buiten het bord ging. verplaatsnoordwesttf :: ToestandFunctie Bool verplaatsnoordwesttf = verplaatstf 0 1 verplaatstf 1 0 isopbord < opbordtf if isopbord then return GeenUitkomst else setcoordinaattf 4 4 return GeenUitkomst return isopbord 25
26 setcoordinaattf :: Int >Int >ToestandFunctie GeenUitkomst setcoordinaattf x y = ToestandFunctie (\begintoestand > let nieuwetoestand = Coordinaat x y in (nieuwetoestand,geenuitkomst Opgave 7 Programmeer zelf de functie gaoonntf die naar het coordinaat eerst naar het oosten, dan weer naar het oosten, dan naar het noorden en dan weer naar het noorden verplaats. Voordat je een stapje et moet je eerst kijken of je or dat stapje niet buiten het bord gaat, anders moet je het stapje niet uitvoeren. Op alle drie de manieren. Dus met: Het steeds expliciet orgeven van de Toestand. De >>= en >> functies. De notatie plus return en if. Je mag hierbij gebruik maken van de al gedefinïeerde functies zoals verplaats. Voeg dit toe aan de file ToestandFunctie.hs Pure functies In een puur functionele taal zoals haskell kunnen we alleen maar pure functies opschrijven. Een eigenschap van pure functies is dat elke keer als je hem uitrekent met dezelfde input er altijd dezelfde output uit moet komen. Als voorbeeld van een functie met deze eigenschap nemen we de cosinus. Elke keer als je bijvoorbeeld cos(0 uitrekent komt er 1 uit. Het zou toch erg verwarrend zijn als er soms iets anders uit komt. In imperatieve talen kunnen wel functies opschrijven waarbij met dezelfde input er soms iets anders uitkomt. Enkele voorbeelden in java hiervan zijn: Scanner.next(, elke keer als je deze aanroept komt er iets anders uit, namelijk de volgende token op de input. Math.ranm(, De java functie verplaatsengaatbuitenbord van hierboven. De uitkomst is afhankelijk van de huidige toestand van het Coordinaat object. 26
27 Een andere eigenschap van een pure-functie is dat hij geen side-effects heeft. Dat wil zeggen dat enkel de uitkomst wordt uitgerekend en er verder niks gebeurt. Als voorbeeld van een functie zonder side-effects nemen we weer de cosinus. Als we deze uitvoeren, berekenen we enkel het resultaat en gebeurt er verder niks. Je zou toch raar staan te kijken als elke keer als je de cosinus uitvoert er nog iets anders gebeurt. In imperatieve talen kunnen wel functies met side-effects opschrijven. Enkele voorbeelden in java hiervan zijn: printf: Er wordt bij deze functie helemaal geen resultaat uitgerekent maar enkel iets op de output geprint, dat is een side-effect. variablen aam = waarde, Als we dit opschrijven in java dan is de uitkomst gewoon waarde, daarom kunnen we bijvoorbeeld x = y = waarde opschrijven in java. Er gebeurt echter nog iets: De variable krijgt een nieuwe waarde. De java functie verplaats en verplaatsengaatbuitenbord, het side-effect is hierbij dat het coordinaat verplaatst wordt. Scanner.next(, als je deze aanroept dan wordt als side-effect de index in de stream gewijzigd. sleep(tijd, als side-effect wacht je een tijdje IO Eigenlijk is bijna elke functie in een imperatieve taal zoals java dus onpuur. De vraag is nu: hoe en we dit soort dingen in een puur functionele taal? Voor de functies verplaats en verplaatsengaatbuitenbord heb je het hierboven al gezien. De oplossing is dat je steeds de toestand meegeeft en dat je de nieuwe toestand met de uitkomst mee geeft. Voor input/output operaties gebruiken we eigenlijk hetzelfde truukje. De toestand die we dan telkens meegeven is de toestand van de hele wereld. Wat voorbeelden hiervan zijn: Als je schrijfoperatie naar een file et, dan verander je de toestand van de hele wereld, er staat nu namelijk iets anders op je hardeschijf. Als je een leesoperatie uit een file et, dan verander je de toestand van de hele wereld, de arm van je harde schijf staat namelijk anders. Als je een berichtje stuurt via internet, dan verander je ook de toestand van de hele wereld, er zit nu namelijk een nieuw pakketje ergens in het wereldwijde netwerk. Als je een opdracht geeft om je CPU-koeler harder laat draaien, dan verander je ook de toestand van de hele wereld, de CPU-koeler draait nu namelijk harder. 27
28 Als je een opdracht geeft om je DVD-lade open te en, dan verander je ook de toestand van de hele wereld, de DVD-lade is nu namelijk open. De toestand van de hele wereld modelleren we in Haskell met het IO type, de implementatie hiervan is niet belangrijk: data IO resultaattype =... Het type GeenUitkomst is in Haskell al gedefineerd, maar dan heet het (: data ( = ( Zo kunnen we dus pure-functies definiëren die de toestand van de hele wereld aanpassen op dezelfde manier waarop we eerst de toestand van het coordinaat aanpasten. Wat voorbeelden hiervan zijn: putstrln :: String > IO ( schrijft een string op de standard output. getline :: IO String leest een string van de standard input. De functies >> en >>= zijn ook gedefiniëerd voor het type IO, ze voeren, net als bij ToestandFunctie, eerst het linker argument uit en dan het rechter. Zo kunnen we bijvoorbeeld een functie schrijven die vraagt om je naam, je naam inleest en daarna Hoi <naam> print. Deze functie veranderd dus de staat van de hele wereld. hallo :: IO ( hallo = (putstrln "Wat is je naam?" >> ( getline >>= (\naam > let hoistring = "Hoi " ++ naam ++ "!" in putstrln hoistring of in de -notatie: hallobeter :: IO ( hallobeter = putstrln "Wat is je naam?" naam < getline let hoistring = "Hoi " ++ naam ++ "!" putstrln hoistring return ( 28
29 De main functie, het beginpunt van elk programma, moet ook het type IO ( hebben. Dus om bijvoorbeeld het programma te maken dat de functie hallo uitvoerd kunnen we schrijven: main :: IO ( main = hallobeter return ( Opgave 8 Programmeer zelf de functie hoiomgekeerd die: Vraagt om je naam Vraagt om je titel (bijv. dhr, mvr of BSc. Uitprint Hoi <je titel> <je naam omgekeerd>!! Op beide manieren. Dus met: De >>= en >> functies. De notatie plus return. Voeg dit toe aan de file Hoi.hs Monads Na dit lange verhaal vraag je je vast af wat nou eigenlijk een monad is. Gelukkig is dat met je nieuwe kennis makkelijk te beantwoorden: Een monad is een type, hierna genoemd m: waarin je een ander type kunt en. Dan krijg je bijvoorbeeld m Bool of m Int. waarop de operator >>= is gedefiniëerd. 2 De operator >>= heeft het type: (m a->(a -> (m b->(m b waarbij a en b willekeurige andere types zijn. waarop de functie return is gedefiniëerd. De functie return heeft het type: a -> (m a waarbij a een willekeurig ander type is. 2 De >> operator is niet noodzakelijk, die kan je definiëren aan de hand van >>= 29
30 Dus bijvoorbeeld: MisschienEen is een monad want: Je kan er een ander type in en, dan krijg je bijvoorbeeld MisschienEen Int of MisschienEen Bool De >>= operator is gedefiniëerd voor MisschienEen De return operator is gedefiniëerd voor MisschienEen. ToestandFunctie is een monad want: Je kan er een ander type in en, dan krijg je bijvoorbeeld Toestand- Functie Int,ToestandFunctie Bool of ToestandFunctie GeenUitkomst. De >>= operator is gedefiniëerd voor ToestandFunctie De return operator is gedefiniëerd voor ToestandFunctie. IO is een monad want: Je kan er een ander type in en, dan krijg je bijvoorbeeld IO Int,IO String of IO (. De >>= operator is gedefiniëerd voor IO. De return operator is gedefiniëerd voor IO. Met een monad kun je dus bijvoorbeeld toestand orgeven, zoals bij ToestandFunctie en IO, of met uitzonderingen omgaan, zoals bij MisschienEen Monads declareren Tot nu toe hebben we gedaan alsof we de >>=,>> en return functies gewoon kunnen opschrijven als alle andere fucnties. Om ze met de -notatie te kunnen gebruiken moeten we echter zeggen dat het type, dus bijvoorbeeld MisschienEen of ToestandFunctie, een instantie van de class Monad is. Dit schrijven we als volgt: Voor MisschienEen: data MisschienEen resultaattype = GeenResultaat Resultaat resultaattype instance Monad MisschienEen where GeenResultaat >>= rechterfunctie = GeenResultaat (Resultaat nummer >>= rechterfunctie = rechterfunctie nummer return x = Resultaat x en voor ToestandFunctie 30
31 data ToestandFunctie resultaattype = ToestandFunctie (Toestand >(Toestand,resultaatType instance Monad ToestandFunctie where (ToestandFunctie functielinks >>= (toestandfunctieonthoudresultaatrechts = ToestandFunctie (\begintoestand > let (tweedetoestand,resultaatlinks = functielinks begintoestand (ToestandFunctie functierechts = toestandfunctieonthoudresultaatrechts resultaatlinks (derdetoestand,resultaatrechts = functierechts tweedetoestand in (derdetoestand,resultaatrechts return uitkomst = ToestandFunctie (\toestand > (toestand,uitkomst 31
32 We gaan nu kijken hoe we een monad kunnen maken waarmee we makkelijk kunnen parsen (ontleden. Dit is een monad die zowel met uitzonderingen omgaat als toestand orgeeft. An Introduction to Parser Combinators 3 The Library Functions The standard Haskell distribution includes the library Parsec, a large and very efficient library of parser combinators. Once you have parsed with Parsec you will refuse to go back to parser libraries for imperative languages like C or Java. However, for the purpose of education we not use Parsec in this course. We implement our own simplistic parser combinator library which we describe in the remainder of this section. We start with a description of the data types. A Parser of type a consists of a function that takes a String and delivers a ParseResult of type a: data Parser a = Parser (String > ParseResult a The ParseResult can either be a Match or NoMatch, corresponding to a successful or non-successful application of the parser, respectively: data ParseResult a = Match a String NoMatch String Note that Match has two parameters. The first is of type a, the result of parsing. The second is the string that remains to be parsed. In case of a non-successful parsing (NoMatch only the remaining string is returned. We now continue with a description of the available parser combinators. These operators are called parser combinators since they combine parsers to new parsers: ( :: Parser a -> Parser a -> Parser a Usage: pa pb Corresponds to (or in BackusNaur Form (BNF. The operator combines to parsers to a new parser which first tries pa and if pa fails, then it tries pb. oneormore :: Parser a -> Parser [a] Usage: oneormore p Corresponds to + in BNF, that is, repeatedly applies the parser p (one or more times. Returns the list of parse results of p. zeroormore :: Parser a -> Parser [a] Usage zeroormore p Corresponds to + in BNF, that is, repeatedly applies the parser p (one or zero times. Returns the list of parse results of p. 32
33 sepby1 :: Parser a -> Parser b -> Parser [a] Usage: sepby1 p sep Parses multiple (but at least one p separated with sep. Returns the list of parse results of p (the results of sep are ignored. sepby :: Parser a -> Parser b -> Parser [a] Usage: sepby p sep Parses multiple p separated with sep. Returns the list of parse results of p (the results of sep are ignored. char :: Char -> Parser Char Usage char c Tries to parse the character c ; fails if the next character is not c. string :: String -> Parser String Usage string s Tries to parse the string s; fails if the string to parse es not start with s. Monads for combining parsers sequentially: composition = result1 < parser1 result2 < parser2... resultn < parsern return your_function(result1,...,resultn Most of these combinators are defined within a single line of code; have a look at the source of Parse.hs. While this library contains already quite useful parser combinators, the great thing is that you can easily define your own ones! Thereby your source code not only gets smaller by factor 10, but also much more readable. 4 Implementation of the Combinators We consider the implementation of two combinators: and the monads for sequential composition are implemented as follows. The combinator is implemented as follows: (Parser pa (Parser pb = Parser (\string > case pa string of NoMatch s > pb string Match a string > Match a string 33
34 That is, pa pb first applies the parser pa. If pa succeeds, then its result is returned. If pa fails, then pb is started on the same input string and its result is returned. 34
35 Monads for sequential composition are implemented as follows: instance Monad Parser where (Parser pa >>= f = Parser (\string > case pa string of NoMatch s > NoMatch s Match a string > let Parser p = f a in p string return a = Parser (\string > Match a string The function >>= is of type: (>>= :: Parser a > (a > Parser b > Parser b That is, pa >>= f is a parser that, given a string s, first applies the parser pa to the string s. If this application is not successful, then NoMatch s is returned. If the application was successful, then we have a result a and a remaining string s. In this case the parser (f a is applied to s and this result is the result of pa >>= f. The function return lifts on object a to a parser returning a as result. That is, return takes an argument a and returns a parser es nothing but leaving returning a as result (and leaving the given string untouched. The notation: composition = result1 < parser1 result2 < parser2... resultn < parsern return your_function(result1,...,resultn is a convenient abbreviation of: composition = parser1 >>= (\result1 > parser2 >>= (\result2 >... parsern >>= (\resultn > Parser (\s > Match your_function(result1,...,resultn s After this dry theory we continue with an example: parsing TRSs. 35
36 5 Parsing TRSs We show how to parse a term rewriting system (TRS given by the following EBNF: trs = whitespace, vars, whitespace, rules, whitespace vars = (, VAR, { wordws }, rules = (, RULES, { rule }+, rule = termws >,termws termws = whitespace, term, whitespace term = word, [ (, [subterms], ] subterms = term, {,, term } word = { symbol }+ wordws = whitespace, word, whitespace symbol = a... z A... Z whitespace = { \n \t } for example: (VAR x y z (RULES f(x,y > g(g(x g(x > a(f(x,x a(z > z The Data Types First, we define the data types for TRSs, rules and terms. data TRS = TRS { variables :: [String], rules :: [Rule] } data Rule = Rule { lhs :: Term, rhs :: Term } data Term = Term String [Term] Var String A TRS consists of a list of variables and a list of rules. A Rule its left-hand side (lhs and a right-hand side (rhs which are both terms. A Term is either a symbol with a list of subterms or a variable. The following example illustrates, how the TRS consisting of the single rule f(x, y g(x can be created in Haskell using the above data types: TRS { variables = ["x","y"], rules = [Rule { lhs = Term "f" [Var "x", Var "y"], rhs = Term "g" [Term "g" [Var "x"]] }] } 36
37 The Parsing First, we define low-level for symbols and words. A symbol is a character a or character b or... In Haskell this can be defined compact using the functions map and foldl1. symbol = foldl1 ( $ map char $ [ a.. z ] ++ [ A.. Z ] ++ [ ] We define a word as a list of symbols: word = oneormore symbol We define a parser to parse the spaces, tab s (\t or linebreak (\n: whitespace = zeroormore (char char \t char \n Now we define a function ws that takes a parser and returns a parser: ws parser = whitespace r < parser whitespace return r Then ws p behaves as p but allows whitespace before and after p. For example wordws behaves as word but allows whitespace before and after the word. wordws = ws word We parse terms: we start with parsing a word, then we parse the subterms (parseterm vars which are wrapped into parenthesis (paren and separated by commas (sepby... (char,. That is: parseterm vars = f < wordws subterms < (paren ( sepby (parseterm vars (char, alwaysmatch let result = if f elem vars then (Var f else (Term f subterms return result Next, we parse rules (two terms separated by -> : parserule vars = l < ws (parseterm vars string " >" r < ws (parseterm vars return (Rule { lhs = l, rhs = r } Finally, we parse the whole TRS which consists of first parsing the list of variables and then the list of rules: 37
38 parsetrs = vars < ws parsevars rules < ws (parserules vars return ( TRS { variables = vars, rules = rules } where parsevars = paren ( string "VAR" vars < zeroormore wordws return vars parserules vars = paren ( string "RULES" rules < oneormore (parserule vars return rules The source code for parsing TRSs can be found on website of the lecture. Opgave 9 Schrijf een parser voor de syntax van de commantaal van de tweede opgave van voortgezet programmeren. Die opgave is te vinden op De datatypen voor de commantaal zijn al gedefineerd in de file ParseStatement.hs. Zet je parser ook in die file. Bonus Opgave niet verplicht Maak de gehele tweede opgave van voorgezet programmeren in Haskell. Hiermee kan je 2 punten bovenop je practicumcijfer winnen. (Dus als je een 7.5 hebt voor het practicum, en je hebt deze opgave gemaakt dan krijg je een 9.5 voor je practicum. Om deze opdracht in te leveren mail je je uitwerking naar [email protected]. 38
inleiding theoretische informatica practicum 1 deadline woensdag 20 februari 2008 om uur
1 Inleiding inleiding theoretische informatica 2007-2008 practicum 1 deadline woensdag 20 februari 2008 om 14.00 uur Dit practicum is een kennismaking met functioneel programmeren. Twee belangrijke functionele
Inleiding tot Func.oneel Programmeren les 3
Inleiding tot Func.oneel Programmeren les 3 Kris Luyten, Jo Vermeulen {kris.luyten,jo.vermeulen}@uhasselt.be Exper.secentrum voor Digitale Media Universiteit Hasselt Currying Currying: een func.e met meerdere
FOR DUTCH STUDENTS! ENGLISH VERSION NEXT PAGE. Toets Inleiding Kansrekening 1 8 februari 2010
FOR DUTCH STUDENTS! ENGLISH VERSION NEXT PAGE Toets Inleiding Kansrekening 1 8 februari 2010 Voeg aan het antwoord van een opgave altijd het bewijs, de berekening of de argumentatie toe. Als je een onderdeel
Als een PSD selecties bevat, deelt de lijn van het programma zich op met de verschillende antwoorden op het vraagstuk.
HOOFDSTUK 3 3.1 Stapsgewijs programmeren In de vorige hoofdstukken zijn programmeertalen beschreven die imperatief zijn. is het stapsgewijs in code omschrijven wat een programma moet doen, net als een
ALGORITMIEK: answers exercise class 7
Problem 1. See slides 2 4 of lecture 8. Problem 2. See slides 4 6 of lecture 8. ALGORITMIEK: answers exercise class 7 Problem 5. a. Als we twee negatieve (< 0) getallen bij elkaar optellen is het antwoord
Programmeermethoden. Recursie. week 11: november kosterswa/pm/
Programmeermethoden Recursie week 11: 21 25 november 2016 www.liacs.leidenuniv.nl/ kosterswa/pm/ 1 Pointers Derde programmeeropgave 1 Het spel Gomoku programmeren we als volgt: week 1: pointerpracticum,
Syntax- (compile), runtime- en logische fouten Binaire operatoren
Inhoud Syntax- (compile), runtime- en logische fouten Binaire operatoren Operaties op numerieke datatypen Evaluatie van expressies, bindingssterkte Assignment operaties en short-cut operatoren Controle
Verzamelingen, Lijsten, Functioneel Programmeren
Verzamelingen, Lijsten, Functioneel Programmeren Jan van Eijck [email protected] Stage Ignatiuscollege, 17 mei 2010 Samenvatting In deze lezing gaan we in op de overeenkomsten en verschillen tussen verzamelingen
FUNCTIONEEL PROGRAMMEREN WEEK 1
FUNCTIONEEL PROGRAMMEREN WEEK 1 T. Busker Bron: Kris Luyten en Jo Vermeulen - Expertise Centrum voor Digitale Media - Universiteit Hasselt Functioneel programmeren? Alles via functies Alles via expressies
Modelleren en Programmeren
Modelleren en Programmeren Jeroen Bransen 6 december 2013 Terugblik Programma en geheugen Opdrachten Variabelen Methoden Objecten Klasse Programma en geheugen Opdrachten Variabelen zijn gegroepeerd in
Verzamelingen, Lijsten, Functioneel Programmeren
Verzamelingen, Lijsten, Functioneel Programmeren Jan van Eijck [email protected] Lezing 4e Gymnasium, 19 november 2015 Samenvatting In deze lezing gaan we in op de overeenkomsten en verschillen tussen verzamelingen
Tentamen Objectgeorienteerd Programmeren
Tentamen Objectgeorienteerd Programmeren 5082IMOP6Y maandag 16 november 2015 13:00 15:00 Schrijf je naam en studentnummer op de regel hieronder. Sla deze pagina niet om tot de surveillant vertelt dat het
The first line of the input contains an integer $t \in \mathbb{n}$. This is followed by $t$ lines of text. This text consists of:
Document properties Most word processors show some properties of the text in a document, such as the number of words or the number of letters in that document. Write a program that can determine some of
Datatypes Een datatype is de sort van van een waarde van een variabele, veel gebruikte datatypes zijn: String, int, Bool, char en double.
Algemeen C# Variabele Een variabele is een willekeurige waarde die word opgeslagen. Een variabele heeft altijd een datetype ( De soort waarde die een variabele bevat). Datatypes Een datatype is de sort
HOOFDSTUK 3. Imperatief programmeren. 3.1 Stapsgewijs programmeren. 3.2 If Then Else. Module 4 Programmeren
HOOFDSTUK 3 3.1 Stapsgewijs programmeren De programmeertalen die tot nu toe genoemd zijn, zijn imperatieve of procedurele programmeertalen. is het stapsgewijs in code omschrijven wat een programma moet
Modelleren en Programmeren
Modelleren en Programmeren Jeroen Bransen 13 november 2015 Expressies Functies Ingebouwde functies Variabelenbereik Inleveropgave 1 Terugblik Programma is een lijst van opdrachten Terugblik Programma is
1 Inleiding in Functioneel Programmeren
1 Inleiding in Functioneel Programmeren door Elroy Jumpertz 1.1 Inleiding Aangezien Informatica een populaire minor is voor wiskundestudenten, leek het mij nuttig om een stukje te schrijven over een onderwerp
Voorbeeld: Simulatie van bewegende deeltjes
Voorbeeld: Simulatie van bewegende deeltjes Simulatie - object Ruimte - objecten Deeltje - objecten Button - objecten Simulatie Samenhang van objecten sim geërfd van Form stap zelf gedeclareerd auto r1
FOR DUTCH STUDENTS! ENGLISH VERSION NEXT PAGE
FOR DUTCH STUDENTS! ENGLISH VERSION NEXT PAGE Tentamen Analyse 6 januari 203, duur 3 uur. Voeg aan het antwoord van een opgave altijd het bewijs, de berekening of de argumentatie toe. Als je een onderdeel
Vakgroep CW KAHO Sint-Lieven
Vakgroep CW KAHO Sint-Lieven Objecten Programmeren voor de Sport: Een inleiding tot JAVA objecten Wetenschapsweek 20 November 2012 Tony Wauters en Tim Vermeulen [email protected] en [email protected]
Programmeren in Java les 3
4 september 2015 Deze les korte herhaling vorige week loops methodes Variabelen Soorten variabelen in Java: integer: een geheel getal, bijv. 1,2,3,4 float: een gebroken getal, bijv. 3.1415 double: een
Universiteit van Amsterdam FNWI. Voorbeeld van tussentoets Inleiding programmeren
Universiteit van Amsterdam FNWI Voorbeeld van tussentoets Inleiding programmeren Opgave 1: Wat is de uitvoer van dit programma? public class Opgave { static int i = 0 ; static int j = 1 ; int i = 1 ; int
Programmeermethoden. Recursie. Walter Kosters. week 11: november kosterswa/pm/
Programmeermethoden Recursie Walter Kosters week 11: 20 24 november 2017 www.liacs.leidenuniv.nl/ kosterswa/pm/ 1 Vierde programmeeropgave 1 De Grote getallen programmeren we als volgt: week 1: pointerpracticum,
Add the standing fingers to get the tens and multiply the closed fingers to get the units.
Digit work Here's a useful system of finger reckoning from the Middle Ages. To multiply $6 \times 9$, hold up one finger to represent the difference between the five fingers on that hand and the first
After that, the digits are written after each other: first the row numbers, followed by the column numbers.
Bifid cipher The bifid cipher is one of the classical cipher techniques that can also easily be executed by hand. The technique was invented around 1901 by amateur cryptographer Felix Delastelle. The cipher
Intermax backup exclusion files
Intermax backup exclusion files Document type: Referentienummer: Versienummer : Documentatie 1.0 Datum publicatie: Datum laatste wijziging: Auteur: 24-2-2011 24-2-2011 Anton van der Linden Onderwerp: Documentclassificatie:
Een korte samenvatting van enkele FORTRAN opdrachten
Een korte samenvatting van enkele FORTRAN opdrachten Inhoud 1 Introductie 3 2 De structuur van een FORTRAN programma 3 3 Datatypen, variabelen en declaraties 3 4 Expressies-volgorde van uitwerking 4 5
Modelleren en Programmeren
Modelleren en Programmeren Jeroen Bransen 13 december 2013 Terugblik Fibonacci public class Fibonacci { public static void main(string[] args) { // Print het vijfde Fibonaccigetal System.out.println(fib(5));
Voorbeeldtentamen Inleiding programmeren (IN1608WI), Oktober 2003, , Technische Universiteit Delft, Faculteit EWI, Afdeling 2.
Voorbeeldtentamen Inleiding programmeren (IN1608WI), Oktober 2003, 14.00-15.30, Technische Universiteit Delft, Faculteit EWI, Afdeling 2. Dit tentamen bestaat uit twee delen. Deel 1 (14.00-14.45, gesloten
FOR DUTCH STUDENTS! ENGLISH VERSION NEXT PAGE
FOR DUTCH STUDENTS! ENGLISH VERSION NEXT PAGE Tentamen Analyse 8 december 203, duur 3 uur. Voeg aan het antwoord van een opgave altijd het bewijs, de berekening of de argumentatie toe. Als jeeen onderdeel
TECHNISCHE UNIVERSITEIT EINDHOVEN Faculteit Wiskunde en Informatica. Examination 2DL04 Friday 16 november 2007, hours.
TECHNISCHE UNIVERSITEIT EINDHOVEN Faculteit Wiskunde en Informatica Examination 2DL04 Friday 16 november 2007, 14.00-17.00 hours. De uitwerkingen van de opgaven dienen duidelijk geformuleerd en overzichtelijk
Inleiding Programmeren 2
Inleiding Programmeren 2 Gertjan van Noord November 26, 2018 Stof week 3 nogmaals Zelle hoofdstuk 8 en recursie Brookshear hoofdstuk 5: Algoritmes Datastructuren: tuples Een geheel andere manier om te
Haskell: programmeren in een luie, puur functionele taal
Haskell: programmeren in een luie, puur functionele taal Jan van Eijck [email protected] 5 Talen Symposium, 12 juli 2010 Samenvatting In deze mini-cursus laten we zien hoe je met eindige en oneindige lijsten
Datastructuren Werkcollege Intro
Bart Hijmans, Universiteit Leiden. Universiteit Leiden The Netherlands Focus 1 19 ˆ Ervaring in gebruik en implementatie van datastructuren ˆ Kennis van mogelijkheden ˆ Programmeren voor andere programmeurs
Calculator spelling. Assignment
Calculator spelling A 7-segmentdisplay is used to represent digits (and sometimes also letters). If a screen is held upside down by coincide, the digits may look like letters from the alphabet. This finding
Wat is FP? The Haskell School of Expression. Functies. Types 1+1=2. Iedere expressie (en waarde) heeft een type.
Wat is FP? The Haskell School of Expression Functioneel Programmeren Een andere manier om tegen programmeren aan te kijken Gebaseerd op het uitrekenen van expressies 1+1=2 Eenvoudig maar krachtig (modulair,
Modelleren en Programmeren
Modelleren en Programmeren Jeroen Bransen 13 november 2013 Organisatie Docenten Jeroen Bransen Michael Moortgat Docenten Jeroen Bransen Imperatief programmeren (Java) Tot de kerst (ongeveer) Michael Moortgat
FOR DUTCH STUDENTS! ENGLISH VERSION NEXT PAGE. Toets Inleiding Kansrekening 1 7 februari 2011
FOR DUTCH STUDENTS! ENGLISH VERSION NEXT PAGE Toets Inleiding Kansrekening 1 7 februari 2011 Voeg aan het antwoord van een opgave altijd het bewijs, de berekening of de argumentatie toe. Als je een onderdeel
Datastructuren: stapels, rijen en binaire bomen
Programmeermethoden Datastructuren: stapels, rijen en binaire bomen week 12: 23 27 november 2015 www.liacs.leidenuniv.nl/ kosterswa/pm/ 1 Inleiding In de informatica worden Abstracte DataTypen (ADT s)
Uitwerking Aanvullend tentamen Imperatief programmeren Woensdag 24 december 2014, 13.30 15.30 uur
Uitwerking Aanvullend tentamen Imperatief programmeren Woensdag 24 december 2014, 13.30 15.30 uur 1. deze opgave telt voor 30% van het totaal. Schrijf een compleet programma, dat door de gebruiker vanaf
Zelftest Inleiding Programmeren
Zelftest Inleiding Programmeren Document: n0824test.fm 22/01/2013 ABIS Training & Consulting P.O. Box 220 B-3000 Leuven Belgium TRAINING & CONSULTING INLEIDING BIJ DE ZELFTEST INLEIDING PROGRAMMEREN Deze
Uitwerking Tweede deeltentamen Imperatief programmeren - versie 1 Vrijdag 21 oktober 2016, uur
Uitwerking Tweede deeltentamen Imperatief programmeren - versie 1 Vrijdag 21 oktober 2016, 13.00-15.00 uur 1. De situatie die ontstaat door class A : B C D; kan beschreven worden door (a) B is een A (b)
Functioneel programmeren
Functioneel programmeren Practicumopgave 2: Mastermind Het doel van deze opgave is het implementeren van het spel Mastermind; zie http://nl.wikipedia.org/wiki/mastermind voor een uitleg. Het spel is klein
Modelleren en Programmeren
Modelleren en Programmeren Jeroen Bransen 25 november 2015 Herhaling Meer herhaling Recursie Mutuele recursie Objecten Herhaling Fibonacci class Fibonacci { public static void fibonaccitot(int bovengrens)
Tentamen Object Georiënteerd Programmeren TI1200 30 januari 2013, 9.00-12.00 Afdeling SCT, Faculteit EWI, TU Delft
Tentamen Object Georiënteerd Programmeren TI1200 30 januari 2013, 9.00-12.00 Afdeling SCT, Faculteit EWI, TU Delft Bij dit tentamen mag je geen gebruik maken van hulpmiddelen zoals boek of slides. Dit
Verzamelingen, Lijsten, Functioneel Programmeren
Verzamelingen, Lijsten, Functioneel Programmeren Jan van Eijck [email protected] Stage Ignatiuscollege, 20 mei 2008 Samenvatting In deze lezing gaan we in op de overeenkomsten en verschillen tussen verzamelingen
FOR DUTCH STUDENTS! ENGLISH VERSION NEXT PAGE
FOR DUTCH STUDENTS! ENGLISH VERSION NEXT PAGE Tentamen Bewijzen en Technieken 1 7 januari 211, duur 3 uur. Voeg aan het antwoord van een opgave altijd het bewijs, de berekening of de argumentatie toe.
Luister alsjeblieft naar een opname als je de vragen beantwoordt of speel de stukken zelf!
Martijn Hooning COLLEGE ANALYSE OPDRACHT 1 9 september 2009 Hierbij een paar vragen over twee stukken die we deze week en vorige week hebben besproken: Mondnacht van Schumann, en het eerste deel van het
Tentamen Programmeren in C (EE1400)
TU Delft Tentamen Programmeren in C (EE1400) 5 april 2012, 9.00 12.00 Faculteit EWI - Zet op elk antwoordblad je naam en studienummer. - Beantwoord alle vragen zo nauwkeurig mogelijk. - Wanneer C code
Tentamen Programmeren in C (EE1400)
TU Delft Tentamen Programmeren in C (EE1400) 3 feb. 2012, 9.00 12.00 Faculteit EWI - Zet op elk antwoordblad je naam en studienummer. - Beantwoord alle vragen zo nauwkeurig mogelijk. - Wanneer C code gevraagd
Classification of triangles
Classification of triangles A triangle is a geometrical shape that is formed when 3 non-collinear points are joined. The joining line segments are the sides of the triangle. The angles in between the sides
Tentamen Imperatief en Object-georiënteerd programmeren in Java voor CKI
Tentamen Imperatief en Object-georiënteerd programmeren in Java voor CKI Vrijdag 22 januari 2010 Toelichting Dit is een open boek tentamen. Communicatie en het gebruik van hulpmiddelen zijn niet toegestaan.
Een typisch programma in C en C++ bestaat uit een aantal onderdelen:
Eerste stappen in C. Een typisch programma in C en C++ bestaat uit een aantal onderdelen: /* Alles wat op meerdere lijnen staat zoals hier is commentaar. */ // Dit is commentaar op 1 lijn. Geldig tot einde
start -> id (k (f c s) (g s c)) -> k (f c s) (g s c) -> f c s -> s c
Een Minimaal Formalisme om te Programmeren We hebben gezien dat Turing machines beschouwd kunnen worden als universele computers. D.w.z. dat iedere berekening met natuurlijke getallen die met een computer
Het relaas van de beginnende programmeur. Het hoe en waarom van de assistent
Het relaas van de beginnende programmeur Het hoe en waarom van de assistent 1. Help, mijn code doet niks... Mogelijke oplossingen: Heb je op run geduwd (groene pijltje)? Zolang je niet op 'run' duwt, kent
Four-card problem. Input
Four-card problem The four-card problem (also known as the Wason selection task) is a logic puzzle devised by Peter Cathcart Wason in 1966. It is one of the most famous tasks in the study of deductive
Tentamen Objectgeorienteerd Programmeren IN1205 Voorbeeld
Tentamen Objectgeorienteerd Programmeren IN1205 Voorbeeld Afdeling ST Faculteit EWI TU Delft Bij dit tentamen mag u gebruik maken van: Barnes, Object-Oriented Programming with Java en de Notitie Algoritmiek
Programmeren met Arduino-software
Programmeren met Arduino-software De software waarin we programmeren is Arduino IDE. Deze software is te downloaden via www.arduino.cc. De programmeertaal die hier gebruikt wordt, is gebaseerd op C en
Modelleren en Programmeren
Modelleren en Programmeren Jeroen Bransen 11 december 2015 Ingebouwde datastructuren Meer boomstructuren Access specifiers Gebruikersinvoer Codestijl Packages SAT-solver Ingebouwde datastructuren Ingebouwde
Opdrachten herhalen. public void tekenscherm (object o, PEA pea) { int x; x = 1; zolang de voorwaarde geldig is
Opdrachten herhalen public void tekenscherm (object o, PEA pea) { int x; x = 1; while ( x
SAMPLE 11 = + 11 = + + Exploring Combinations of Ten + + = = + + = + = = + = = 11. Step Up. Step Ahead
7.1 Exploring Combinations of Ten Look at these cubes. 2. Color some of the cubes to make three parts. Then write a matching sentence. 10 What addition sentence matches the picture? How else could you
Tentamen Programmeren in C (EE1400)
TU Delft Faculteit EWI Tentamen Programmeren in C (EE1400) 28 jan 2011, 9.00 12.00 - Zet op elk antwoordblad je naam en studienummer. - Beantwoord alle vragen zo nauwkeurig mogelijk. - Wanneer C code gevraagd
Opgave 2 Geef een korte uitleg van elk van de volgende concepten: De Yield-to-Maturity of a coupon bond.
Opgaven in Nederlands. Alle opgaven hebben gelijk gewicht. Opgave 1 Gegeven is een kasstroom x = (x 0, x 1,, x n ). Veronderstel dat de contante waarde van deze kasstroom gegeven wordt door P. De bijbehorende
Hoofdstuk 0. Van Python tot Java.
Hoofdstuk 0. Van Python tot Java. In dit eerste hoofdstuk maken we de overstap van Python naar Java. We bespreken de verschillen en geven wat achtergrondinformatie. In het volgende hoofdstuk gaan we dieper
extra oefening algoritmiek - antwoorden
extra oefening algoritmiek - antwoorden opgave "Formule 1" Maak een programma dat de gebruiker drie getal A, B en C in laat voeren. De gebruiker zorgt ervoor dat er positieve gehele getallen worden ingevoerd.
Logisch en Functioneel Programmeren voor Wiskunde D
Logisch en Functioneel Programmeren voor Wiskunde D Wouter Swierstra Doaitse Swierstra Jurriën Stutterheim Technical Report UU-CS-2011-033 Sept 2011 Department of Information and Computing Sciences Utrecht
OEFENINGEN PYTHON REEKS 1
Vraag 1: Expressies & Types OEFENINGEN PYTHON REEKS 1 Python maakt gebruik van enkele vaak voorkomende (data)types. Zo zijn er integers die behoren tot de gehele getallen (VB: 3), zijn er float s die behoren
Tweede deeltentamen Mobiel programmeren - versie 1 Vrijdag 2 februari 2018, uur
Tweede deeltentamen Mobiel programmeren - versie 1 Vrijdag 2 februari 2018, 8.30-10.30 uur Schrijf op elk ingeleverd blad je naam. Schrijf op het eerste blad ook je studentnummer en het aantal ingeleverde
Scala. Korte introductie. Sylvia Stuurman
Korte introductie Sylvia Stuurman Wat is er zo bijzonder aan? Schaalbaar Objectgeoriënteerd (handiger dan Java!) Functioneel Scripts schrijven Gecompileerd: Java bytecode Pagina 2 voor scripts Pagina 3
compileren & interpreteren - compileren: vertalen (omzetten) - interpreteren: vertolken
compileren & interpreteren - compileren: vertalen (omzetten) - interpreteren: vertolken - belangrijkste punten: - ontleden van de programmatekst - bijhouden van de datastructuren Data Structuren en Algoritmen
Zo gaat jouw kunstwerk er straks uitzien. Of misschien wel heel anders.
Spirograaf in Python Een kunstwerk maken Met programmeren kun je alles maken! Ook een kunstwerk! In deze les maken we zelf een kunstwerk met Python. Hiervoor zal je werken met herhalingen en variabelen.
FOR DUTCH STUDENTS! ENGLISH VERSION NEXT PAGE. Toets Inleiding Kansrekening 1 22 februari 2013
FOR DUTCH STUDENTS! ENGLISH VERSION NEXT PAGE Toets Inleiding Kansrekening 1 22 februari 2013 Voeg aan het antwoord van een opgave altijd het bewijs, de berekening of de argumentatie toe. Als je een onderdeel
MyDHL+ Van Non-Corporate naar Corporate
MyDHL+ Van Non-Corporate naar Corporate Van Non-Corporate naar Corporate In MyDHL+ is het mogelijk om meerdere gebruikers aan uw set-up toe te voegen. Wanneer er bijvoorbeeld meerdere collega s van dezelfde
Uitwerkingen derde deeltentamen Gameprogrammeren Vrijdag 6 november 2015, uur
Uitwerkingen derde deeltentamen Gameprogrammeren Vrijdag 6 november 2015, 11.00-13.00 uur 1. Deze opgave bestaat uit een aantal deelvragen. Houd het antwoord kort: één of twee zinnen per onderdeel kan
General info on using shopping carts with Ingenico epayments
Inhoudsopgave 1. Disclaimer 2. What is a PSPID? 3. What is an API user? How is it different from other users? 4. What is an operation code? And should I choose "Authorisation" or "Sale"? 5. What is an
HOGESCHOOL VAN AMSTERDAM Informatica Opleiding. CPP 1 van 10
CPP 1 van 10 ADSdt 1-2009 TENTAMENVOORBLAD Voor aanvang van het tentamen s.v.p. de tentamengegevens goed doorlezen om eventuele misverstanden te voorkomen!! Naam student : Studentnummer : Groep : Studieonderdeel
Inleiding Programmeren 2
Inleiding Programmeren 2 Gertjan van Noord November 28, 2016 Stof week 3 nogmaals Zelle hoofdstuk 8 en recursie Brookshear hoofdstuk 5: Algoritmes Datastructuren: tuples Een geheel andere manier om te
TOEGANG VOOR NL / ENTRANCE FOR DUTCH : https://www.stofs.co.uk/en/register/live/?regu lator=c&camp=24759
DISCLAIMER : 1. Het is een risicovolle belegging / It is an investment with risc. 2. Gebruik enkel geld dat u kan missen / Only invest money you can miss. 3. Gebruik de juiste procedure / Use the correct
http://www.liacs.nl/home/kosters/java/
sheets Programmeren 1 Java college 2, Walter Kosters De sheets zijn gebaseerd op de hoofdstukken 2 tot en met 6 van: D. Bell en M. Parr, Java voor studenten, Prentice Hall, 2002 http://www.liacs.nl/home/kosters/java/
How to install and use dictionaries on the ICARUS Illumina HD (E652BK)
(for Dutch go to page 4) How to install and use dictionaries on the ICARUS Illumina HD (E652BK) The Illumina HD offers dictionary support for StarDict dictionaries.this is a (free) open source dictionary
II. ZELFGEDEFINIEERDE FUNCTIES
II. ZELFGEDEFINIEERDE FUNCTIES In Excel bestaat reeds een uitgebreide reeks van functies zoals SOM, GEMIDDELDE, AFRONDEN, NU enz. Het is de bedoeling om functies aan deze lijst toe te voegen door in Visual
Informatica: C# WPO 2
Informatica: C# WPO 2 1. Inhoud If, globale variabelen, debuggen, randomgetallen, strings vergelijken 2. Oefeningen Demo 1: Deelbaar door 0 Demo 2: Kassa Demo 3: Debug oplossingen demo s 1 en 2 A: Verschillend
Stacks and queues. Hoofdstuk 6
Hoofdstuk 6 Stacks and queues I N T R O D U C T I E In dit hoofdstuk worden drie datastructuren stack, queue en deque behandeld. Om deze datastructuren te implementeren, worden onder andere arrays en linked
Practicumopgave 3: SAT-solver
Practicumopgave 3: SAT-solver Modelleren en Programmeren 2015/2016 Deadline: donderdag 7 januari 2016, 23:59 Introductie In het vak Inleiding Logica is onder andere de propositielogica behandeld. Veel
Cambridge Assessment International Education Cambridge International General Certificate of Secondary Education. Published
Cambridge Assessment International Education Cambridge International General Certificate of Secondary Education DUTCH 055/02 Paper 2 Reading MARK SCHEME Maximum Mark: 45 Published This mark scheme is published
Programmeren (1) Examen NAAM:
Schrijf al je antwoorden op deze vragenbladen (op de plaats die daarvoor is voorzien) en geef zowel klad als net af. Bij heel wat vragen moet je zelf Java-code schrijven. Hou dit kort en bondig. Je hoeft
DOMjudge teamhandleiding
judge DOMjudge teamhandleiding Samenvatting /\ DOM DOM judge Hieronder staat de belangrijkste informatie kort samengevat. Dit is bedoeld om snel aan de slag te kunnen. We raden echter ten zeerste aan dat
HOOFDSTUK 3. Imperatief programmeren. 3.1 Stapsgewijs programmeren. 3.2 If Then Else. Informatie. Voorbeeld. Voorbeeld: toegangsprijs
HOOFDSTUK 3 3.1 Stapsgewijs programmeren De programmeertalen die tot nu toe genoemd zijn, zijn imperatieve of procedurele programmeertalen. is het stapsgewijs in code omschrijven wat een programma moet
Inleiding programmeren
Inleiding programmeren Docent: José Lagerberg Assistenten: Robin de Vries, Jordy Perlee, Dimitri Belfor, Stephen Swatman, Erik Kooistra, Daan Kruis, Daniel Louwrink Cursusinformatie: https://staff.fnwi.uva.nl/j.m.lagerberg
Programmeren in Java 3
2 september 2007 voor deeltijdstudenten Kop van Zuid Rotterdam, 3 juni 2007 Even voorstellen Naam: Wessel Oele(31) Docent bij opleiding technische informatica Kamer: I210 (tweede verdieping, links de gang
