Kungliga Tekniska Högskolan Ämneskod 2D1370 Nada Tentamensdag 2001-maj-31 Tentamen i Funktionell Programmering Skrivtid 4 h Antalet uppgifter : 4 ( 8p +10p + 10p +12p = 40 p) Lärare, jourhavande lärare : Leif Kusoffsky ------------------------------------------------------------------------------------------------------------------ Tillåtna hjälpmedel: Hudak : The Haskell School of Expression Jones et al :Report on the Programming Language Haskell 98 (Häfte + appendix) ----------------------------------------------------------------------------------------------------------------- 1 Skriv en funktion tobig :: Char -> Char som förvandlar små engelska bokstäver a <= bokstav <= z och å, ä, ö till motsvarande stora bokstäver. 8p) 2 En multimängd eller på engelska en bag är en mängd där antalet förekomster spelar roll. T ex är en bag med {2,1} inte detsamma som {1,2,2}. I motsats till listor spelar dock ordningen ingen roll, {1,2,2} är det samma som {2, 1,2}. Definiera i Haskell en ADT (abstrakt datatyp) med följande operationer: empty Resultat: En tom bag insert x b Resultat: En ny bag med elementet x + elmenten i bagen b count x b Resultat: Antalet x i b. remove x b. Resultat: En ny bag som bagen b men med ett x mindre. Skall ge felmedelande om count x b < 1. Implementera ADT bag som ett binärt sök-träd med infomation om ett visst elementet och antalet förekomster av detta element i bagen i en nod. Det är OK om det i trädet finns noder där antalet förekomster är noll. Lämplig intern implementation: data Bag a = Tip Node a Int (Bag a) (Bag a) t Skriv typen för varje metod. (det krävs förståss ingen balansering eller optimering av sök-trädet) 10p)
3 I Haskell kan man lätt arbeta med typen String som ju enbart är en typsynonym för teckenlistor, dvs type String = [Char] För värden av typen String kan man använda <,<=, >, >=, == osv. Problemet är att Å och Ä, å och ä kommer i fel ordning. Dessutom vill man ofta att det inte skall spela någon roll om orden skrivs med små eller stora bokstäver när man använder relationsoperqtorer. Skriv en modul StringLK som definierar en typ StringLK som skall vara en instans av typklassen Ord så klassens operationer fungerar korrekt för det svenska alfabetet och struntar i stora och små bokstäver. a) Skriv bara det som behövs för att operationer och funktioner i Ord ska fungera. Tips : Läs gärna om typklassen Ord i avsnitt 24.1 i kap 24 i boken. Tänk på klassers "default"-definitioner, som det bekvämare att lösa uppgiften. Jag fick användning tobig av från uppgift 1, som får användas även om uppgift 1 ej lösts. b) Definiera en funktion lift2 :: ([Char] -> [Char] -> [Char]) -> (StringLK -> StringLK -> StringLK) så att binära operationer/funktioner för typen type String = [Char] kan användas StringLK. T ex så att man kan skriva (lift2 (++)) (StringLK "hej" )(StringLK "san") för att konkatenera och få resultatet StringLK "hejsan" c) Skriv även lift0 :: [Char] -> StringLK lift1 :: ([Char] -> [Char]) -> (StringLK -> StringLK) d) Skriv en funktion tobigstringlk :: StringLK -> StringLK som förvandlar t ex tobigstringlk (StringLK "hej") till (StringLK "HEJ") Tips : Definitionen går att skriva mycket kortfattat med användning av bl a tobig av från uppgift 1, som får användas även om uppgift 1 ej lösts. 10p)
4. a) Skriv i FAL (Hudak kap 15) ett program Spegel som gör att en gul rektangel som följer musmarkörens röelsersom följer"speglar sig ch blir blå" i en "spegel". Blå rektangel som är den virtuella bilden av den gula rektangeln och som följer den gula rektangeln spegelvänt Spegeln Gul rektangel som följer musen a) Läs problemt så att "spegling" sker vare sig den blå rektangeln är till vänster eller till höger om spegeln. b) Modifera lösningen så att spegling sker bara när den blå rektangeln är till vänster om spegeln. I övriga fall så "parkeras" den blå rektangeln i mitten av spegeln. Denna något mer realistiska spegel kan dock inte gå sönder och den gula rektangeln kan passera genom spegeln och vara på båda sidor om spegeln. 12p)
Förslag till svar tentamen i Funktionell Programmering 2D1370 2001-maj-31 tobig :: Char -> Char -- 1 tobig c a <= c && c <= z = toenum(fromenum c - 32) c == ö = Ö c == å = Å c == ä = Ä otherwise = c module Bag(Bag,empty,insert,remove,count) --2 data Bag a = Tip Node a Int (Bag a) (Bag a) empty = Tip insert :: Ord a => a -> Bag a -> Bag a insert x Tip = Node x 1 Tip Tip insert x (Node e c left right) x == e = Node e (c+1) left right x < e = Node e c (insert x left) right x > e = Node e c left (insert x right) remove :: Ord a => a -> Bag a -> Bag a remove x Tip = error ("remove error in Bag") remove x (Node e c left right) x == e && c > 0 = Node e (c-1) left right x < e = Node e c (remove x left) right x > e = Node e c left (remove x right) otherwise = error ("remove error: in Bag") count:: Ord a => a -> Bag a -> Int count x Tip = 0 count x (Node e c left right) x == e = c x < e = count x left x > e = count x right
module StringLK -- 3 a) data StringLK = StringLK [Char] deriving (Show) instance Eq StringLK (==) (StringLK s1) (StringLK s2) = map tobig s1 == map tobig s2 instance Ord StringLK (<=) (StringLK s1) (StringLK s2) = leqq s1 s2 leqq :: [Char] -> [Char] -> Bool leqq c1 c2 = leq (map tobig c1) (map tobig c2) leq :: [Char] -> [Char] -> Bool leq ( Å : cs) ( Ä : ds) = True leq ( Ä : cs) ( Å : ds) = False leq ( c : cs) ( d : ds) c == d = leq cs ds c <= d = True leq [] ( d: ds) = True leq ( c: cs) [] = False leq [] [] = True lift2 :: ([Char] -> [Char] -> [Char]) -> -- 3 b) (StringLK -> StringLK -> StringLK) lift2 f (StringLK str1) (StringLK str2)= StringLK (f str1 str2) lift0 :: [Char] -> StringLK -- 3c) lift0 = StringLK lift1 :: ([Char] -> [Char]) -> (StringLK -> StringLK) lift1 f (StringLK str) = StringLK (f str) tobigstringlk :: StringLK -> StringLK tobigstringlk = lift1 (map tobig) --3d
module Spegel -- 4 import Picture(Picture, Region, containsr) import Fal main :: IO() main = test (sbild over mirror over obj ) sbild, obj, mirror :: Behavior Picture mirrorat ::(Behavior Float, Behavior Float) mirrorat = ( 0.0, 0.0) mirrorb, sbildb :: Behavior Region mirrorb = rec 7 70 sbildb = rec 5 5 mirror = paint white (translate mirrorat mirrorb) obj = paint yellow (translate mouse sbildb) s :: Behavior (Float, Float) {- -- Uppgift a s = (pairb (xx- mx) my) (xx, yy) = mirrorat -} sbild = paint blue (translate mirrorat (translate (fstb s, sndb s) sbildb) ) -- Uppgift b s = (pairb 0.0 0.0) switch ( (totheright ->> (pairb ( xx - mx) my)).. (totheleft ->> pairb 0.0 0.0 )) (xx, yy) = mirrorat totheright = when (mx >* 0.0) totheleft = when (mx <* 0.0)