Föreläsning 4 i programmeringsparadigm. OBS! Schemat ändrades den 30 augusti.,om du tryckte ut schemat tidare, märk att det är ingen föreläsning 2005 sept 14 onsdag, däremot 2005 sept 20 13.00 i sal F1. Introduktion till Schacklabben. De första stegen. Grafik. Se labhäftet 14 <= sidan <= 22. Repetition och kompletteringar 1<= Hutton kapitel <= 6. Att vi inte följt Hutton så noga beror på att Hutton inte skrivit klart sitt kapitel 10 om egendefinierade typer, och vi behövde detta från början i schacklabben. Men vi har berört mycket av det som står i de sex första kapitlen, det är dags att komplettera och repetera. Kapitel 1. 1.1 "Körningar" av Haskell-skript ("Haskell-program", dvs def av funktioner, typer, moduler) == förenklingar av uttryck. 1.2, 1.3, 1.4. Jag har försökt förmedla liknade ideer. 1.5 Def av sum och "körning" av sum har vi gjort. Jag kommer att säga några ord om sånt som Num a =>. a.. Betyder ungefär "alla typer a som finns i typklassen Num", t ex Int, Float qsort är ett exempel på hur man skriver sorteringssättet quicksort. Kan ni quicksort från indan, läs gärna detta. Vad [ <- ] betuder, senare i denna förläsning eller Hutton kap 5. Konstruktoroperatorn : och operatorn ++: : är en konstuerar-operator som är definierad i deklarationen för datatypfamilen lista i preluden dvs ungefär data [a] = (:) a [ a] -- typ (:) :: a->[a]->[a], [] dvs resultat när man använder :är en ny lista med godtyklig typ a, [a], som består av argumentet av typ a som första element och sedan följer elementen i argumentet (listan) av typ [a]. 3: [ 14,56] blir [3, 14,56] kan också skrivas 3: (14 : 56: []) blir 3: 14 : 56: [] h : [ e, j ] blir [ h, e, j ] kan också skrivas h : ( e : j : [])blir h : 14 : j : [] eller kan också skrivas h : "ej" blir "hej" Eftersom : är definierad i deklarationen för datatypfamilen lista så kan : ingå i mönster (patterns) dvs sum (x:xs) =...
++ är en konstuerar-operator som är definierad i preluden och har typen (++) : [a] -> [a] -> [a], dvs resultat är en ny lista med godtyklig typ a, [a], som består av listargumentet av typ [a] som första element och sedan följer elementen i argumentet (listan) av typ [a]. [4,12] ++ [ 14,56] blir [4,12, 14,56] [ h, e ] ++ [ j ] blir [ h, e, j ] kan också skrivas "he" ++ "j" blir "hej" Eftersom ++ är definierad i preluden (och Hutton sid 164) som en helt vanlig operator,dvs (++) är en helt vanlig funktion,så kan inte ++ ingå i mönster (patterns) när man definierar funktioner. Kapitel 2. 2.1 2.2 2.3, 2.4 Motsvarar introduktionen i labhäftet. Här använder Hutton funktioner från preluden. Tips om hur man hittar i preluden mm finns i förläsningsanteckningarna från föreläsning 3, jag tat upp detta nu. De vanligaste finns också i Hutton häftet Appendix B, sid 157. Märk hur korta definitionerna är, det är nästan lika bevämt att skriva dem själv om man inte vet att de finns. Hutton använder ord och chr, men dessa funktioner finns inte alltid i preluden, använd då toenum :: Enum a => Int -> a fromenum :: Enum a => a -> Int Exempel: fromenum a blir 97, (toenum 97)::Char blir a. Andra uttrycket är en av de sälsynta tillfällen man måste "hjälpa" Haskell med vilken typ man vill ha. Används toenum som hjälpfunktion i en funktionsdefinintion som man typat behövs inte detta. Appendix A, sid 156. är viktigt när man läser Hutton. Av någon anledning, kanske kärlek till matematiken, skriver inte Hutton riktig Haskell utan använder mera matematiska tecken ibland. Layout-regeln 2.4.3 viktig. Gör man fel skriver ofta hugs att den saknar ;, vilket beror på att det finns ett sätt att skriva skript utan layout-regeln. Regeln används dock säkert av 99% av alla haskellprogrammerare. Kapitel 3. 3.1 3.2 3.3, 3.4 3.5 3.6, 3.7. Mest repetition. Jag kommer också att säga en del om 3.8 och 3.9. Kapitel 4. 4.1 4.2 4.3.Mest repetition.
I 4.4 definierar vi && (Hutton använder den matematiska symbolen och gör infix definiton av operator). Jag brukar göra så här så att man ser att det är en funktion man definierar: andlk :: Bool -> Bool -> Bool andlk True True = True andlk = False (&&) = andlk -- && finns förstås i Preluden och bör ju inte omdefinieras 4.4.3 Är dumt enligt många, ingår inte i kursen. 4.5 Lamda-uttryck. Lamda skrivs \ i Haskell. Detta har vii nte talat om än; jag gör det nu p ss som Hutton. 4.6 Hoppar vi över tills vidare. Kapitel 5. Listomfattning. (List comprehensions, Hutton kap 5, Fokker 3.2.7) 5.1 Med listomfattning (List comprehension) skriva väldigt eleganta program, lätta att skriva och förstå. Några delar av Schack-labben blir enklare att skriva med listomfattning än med hjälpfunktioner. Vi ska ju ofta göra något med en listor, t ex listor med grafik. Exempel, vår kära power: power :: Int -> Int -> Int -- Om man kan listomfattning power m n = product [m x <- [1..n]] Syntaxen påminner om matematikens syntax för mängder : {x*x x e N, 1 <= x, x <= 10} Utvikning : Listomfattning i steg 3b. I steg 3b skall vi skriva en funktion polygonpicture :: [Vector] -> Vector -> Float -> Color -> Graphic i modulen PolygonGraphics genom att, kombinera withcolor, polygon från SOEGraphics topixels i modulen själv (PolygonGraphics ) mscal, vadd från Vector Detta kan göras med listomfattning. Här är ett exempel på nåt liknade:l partilltrippel :: a -> (b,c) -> (b,c,a) partilltrippel c (a,b) = (a, b, c) skalatrippel :: Num a => a -> (a,a,a) -> (a,a,a) skalatrippel x (a, b, c) = (a*x, b*x, c*x) sumtrippel :: Num a => (a,a,a) -> a sumtrippel (a, b, c) = a+b+c
exempel :: Num a => [(a,a)] -> a -> a -> a exempel massapar tilll skala = sum [sumtrippel(skalatrippel skala (partilltrippel tilll (a,b))) (a,b)<-massapar] exempel tar en lista med par, lägger till en komponent tilll så vi får en lista med tripplar, sklar tripplarna med skala, summerar varje trippel så vi får en lista med tal, summer dessa tal. Körning: exempel [(3, 5),(14, 28), (19, 2)] 5 10 blir 860 Resten av kapitel 5. 5.2 I listomfattningar kan vi också använda vakter. 5.3. Bra funktion att kunna, men vi kan hopa över detta tills vidare. 5.4. Viktigt, vi har ofta betonat att type String = [Char] type skapar namn på typsynonymer, dvs ytterligare namn på typer som redan finns, och inte "äkta" nya typer som man ju skapar med data Nytyp =.... Ytterligare typsynonymer finns i SOEGraphics : type Graphic = Draw () type Point = (Int, Int). kan vara bra att kunna så man inte blir rädd i schackprojektet där hugs ibland skriver Graphic eller Pointi typuttryck. Jag brukar inte använda typsynonymer, men vissa författare tycker att typuttryck blir mer lättlästa om man gör det. 5.5 Exempel på användning. Läs dett om du har lust. Kapitel 6. 6.1 Liknade problem som vi behandlade i första labben. Definintion av * brukar jag inte göra infixt som Hutton gör, jämför hur jag definierar && ovan. 6.2.6.3 Standardexempel på hur man gör massor av olika funktioner på listor, och om man tittar på listfuktioner i preluden finns ännu fler exempel. Genom att skriva lämpliga definitioner på listfunktioner (ofta 2-3 rader)kan man själv lösa det mesta utan att behöva använda prelude-funktionerna eller t ex listfunktioner, men det är ju onödigt "att uppfinna hjulet igen". Detta är nog anledningen att Hutton väntar med att skriva om rekursion på listor till kapitel 6. Ännu fler jättesmarta, och generella, funktioner kan vi förtå sedan vi senare läst kapitel 7. Enkel rekursion motsvara ofta lösningar med "loopar" i imperativa språk. 6.4, 6.5. Exempel på lite svårare rekursiva funktioner. Motsvarande lösningar i imperativa språk är ofta svåra att skriva utan rekursion, så även i dessa språk används rekursion om det är tillåtet. 6.6 Motsvarar något "definition av funktioner i Haskell", sid 11 i labhäftet..
Nada Tentamensdag 2003 aug 25 Tentamen Programmeringsparadigm Skrivtid 5 h Antalet uppgifter : 1 (allmänt)+ 4 (Haskell) + 4 (Prolog) = 5p +(12p + 15p +5p+ 20p) + (10p +14p + 8p +11p) = 5p + 52p + 43 p = 100p Lärare, jourhavande lärare : Leif Kusoffsky ------------------------------------------------------------------------------------------------------------------ Tillåtna hjälpmedel: Fokker : Functional programming Brna : Prolog Programming ----------------------------------------------------------------------------------------------------------------- På lektionen hann vi endast göra 3a 3c och 3d på lektionen. I lektion 3 har vi inte talat om ADT Date. Del : Paradigmer allmänt. 1. a) Kan man programmera icke-objekt-orienterat i Java, dvs som i ett klassikt imperativt språk? 1) Nej, går ej att skriva program som är i stort ekvivalenta med t ex Pascal-program. X) Ja, om man undviker switch- och if-kommandon 2) Ja, i stort sett om klasserna enbart har variabler och funktioner deklarerade som static. b) Om man programmerar objekt-orienterat i Java 1) Har ofta subklasser egna olika implementaioner av metoder definierade i den gemensamma superklassen. X) Kan man använda multipelt arv 2) Har klasserna enbart metoder deklarerade som static. c) Föjande språk är imperativa, icke-objekt-orienterade språk 1) Pascal, Fortran, C, BASIC X) Prolog 2) Smalltalk, Eiffel, Simula d) I vilken pardigmen programmerar man genom att ange i vilken ordning datorn skall utföra olika kommandon, kommandon som ofta har sidoeffekter? 1) Logiska läsningen i den logiska paradigmen X) Funktionella paradigmen 2) Imperativa paradigmen och objekt-orienterade paradigmen e) Assembleringsspråk användes när datorer var nyuppfunna, dvs på 50-talet. Vilken paradigm? 1) Logiska paradigmen X) OO- paradigmen 2) Imperativ paradigmen 5p)
Del : Funktionell programmering. I alla deluppgifterna, använd Haskell och skriv typen för de identifierare du definierar. 2. a) Skriv en funktion distbetween:: ((Float, Float), (Float, Float)) -> Float som givet ett par med två kordinater ((x1, y1), (x2, y2)) i ett rätvinkligt koordinatsystem returnerarar avståndet mellan koordinaterna. Exempel..> distbetween ((0.0, 0.0), (3.0, 4.0)) blir 5.0 6p) b) Definiera triarea :: (Float, Float) -> (Float, Float) -> (Float, Float) -> Float som givet koordinaterna för tre hörn i ett rätvinkligt kordinatsystem returnerarar arean för triangeln bestämd av de tre hörnen. Tips: Använd Herons formel : A = sqrt (s*(s-a)*(s-b)*(s-c)) där a, b, c är längden på triangels sidor och s = 0.5*(a+b+c) 6p) På lektionen hann vi endast göra 3a 3c och 3d på lektionen. I lektion 3 har vi inte talat om ADT Date. 3. Definiera en funktion productbiggerthan :: Int -> [(Int, Int)] -> [Int] productbiggerthan k list multipliserar komponenterna i paren i list och retunerar en lista med de produkter som är större än k. Exempelvis: productbiggerthan 5 [(1, 2),(3, 4),(5, 6)] blir [12, 30] eftersom 3*4 > 5 och 5*6 > 5 a) Skriv funktionen utan att använda några högre ordningens funktioner eller listomfattning. (och inte som i uppgift d) b) Skriv funktionen med map och filter. c) Skriv funktionen med listomfattning. d) Skriv funktionen med hjälpfunktion med "accumulering i parameter". 15p) 4. I ett typuttrycket kan det stå Num a =>. Förklara vad som menas med detta. Vilkets sorts namn är Num? 5p)
5 a) Skriv i Haskell en modul för en datatype Shape för några olika geometriska former. Man skall kunna definera värden som är rektanglar givet två sidor cirklar givet radien rätvinkliga trianglar givet de två katetrarna polygoner givet en lista med kordinater för hörnen Dessutom skall det finnas (exporteras) en vanliga funktion square (ej konstuerarfunktion) som returnerar en kvadrat (givet sidan). Till slut skall det i ADT Shape finnas (exporteras) en funktion area :: Shape -> Float som retunerar arean för en geometrisk form (se även fråga b). Tips: Polygoners yta kan beräknas genom att dela upp en polgon i en mindre polygon och en triangel (för triangelns yta kan du använda funkitonen i 2 b): v1 v2 v5 v3 v4 v2 v3 = + v1 v1 v5 v3 v4 b) För att kontrollera funktionen area, skriv två uttryck vars värden utgör arean på en kvadrat med sidan 1, det ena uttrycket med kvadraten beskriven med funktionen square och det andra uttrycket med kvadraten beskriven med konstuerarfunktionen för polygoner, dvs kvadraten beskrivs som en polygon med fyra hörn i (0, 0), (1, 0), (1, 1), (0,1). Låt oss kalla värdet på de två uttrycken som u1 och u2. Diskutera vilket värde u1 == u2 kan få. c) På IKEA kan man tänka sig att man kan inhandla en rund cylindrisk kastrull med radien 3.0 och höjden 4.0. Skriv ett uttryck vars värde utgör kastrullens volym. Förslag till svar tentamen programeringsparadigm 2003- aug. Del paradigmer allmänt. 1a) 2 1b) 1 1c) 1 1d) 2 1e) 2
Del funktionell programmering. distbetween :: ((Float, Float),(Float, Float)) -> Float -- 2a) distbetween ((x1, y1), (x2, y2)) = sqrt ((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)) triarea :: (Float, Float) -> (Float, Float) -> (Float, Float) -> Float -- 2b) triarea v1 v2 v3 = sqrt (s*(s-a)*(s-b)*(s-c)) where a = distbetween (v1, v2) b = distbetween (v2, v3) c = distbetween (v3, v1) s = 0.5*(a+b+c) productbiggerthan _ [] = [] -- 3 a productbiggerthan k ((i, j):ijs) i*j > k = (i*j) : productbiggerthan i ijs otherwise =productbiggerthan i ijs productbiggerthan k list = filter p (map f list) -- b where f (i, j) = i*j p m = m > k productbiggerthan k list = [ i*j (i,j) <- list, i*j > k ] -- c productbiggerthan k list = pbtacc k list [] -- d pbtacc :: Int -> [(Int, Int)] -> [Int] -> [Int] pbtacc _ [] acc = acc pbtacc k ((i, j):ijs) acc i*j > k = pbtacc k ijs (acc++[i*j]) otherwise = pbtacc k ijs acc -- 4 T ex Num a => a -> a -> a. Num a är ett sammanhang ("context") för typuttrycket a -> a -> a, dvs i typuttrycket står a för någon typ som är en instans ("instance") av typklassen Num. Det innebär att a står för någon typ som har operationerna/funktionera i Num dvs +, - *, negate, abs, signum och tointeger. Dessa operationer/funktioner har typer som finns i deklarationen för typklassen Num. module Shape (Shape(..), area, square) where -- 5 a) data Shape = Rectangle Float Float Circle Float RtTriangle Float Float Polygon [(Float, Float)] square :: Float -> Shape square s = Rectangle s s -- distbetween, triarea se uppgift 2 area :: Shape -> Float area (Rectangle s1 s2 ) = s1*s2 area (Circle r ) = r * r * pi area (RtTriangle s1 s2 ) = 0.5*s1*s2 area (Polygon (v1:v2:v3:[])) = triarea v1 v2 v3 area (Polygon (v1:v2:v3:vs)) = triarea v1 v2 v3 + area (Polygon (v1:v3:vs)) Shape> area (Polygon [ (0, 0), (1, 0), (1, 1), (0,1)]) -- 5 b) 1.0 Shape> area (square 1) 1.0 Shape> area (Polygon [ (0, 0), (1, 0), (1, 1), (0,1)]) == area (square 1) False -- "Borde" bli True, men sqrt i Herons formel med serieutveckling ger -- ej exakt värde. == Farligt för värden av typ Float Shape> 4.0*area (Circle 3.0) -- 5 c) 113.097