UMEÅ UNIVERSITET Datavetenskap 020321 Betygsgränser 0 19,5 U 20 25,5 3 26 31,5 4 32-40 5 LÖSNINGSFÖRSLAG TENTAMEN 020321 PROGRAMMERING I ETT FUNKTIONELLT SPRÅK ML, 5P Uppgift 1(3+2=5 poäng) I denna uppgift skall du jobba med en abstrakt datatyp (abstype) som skall representera en kö (värden av olika typ skall kunna lagras i kön) Operationer som skall kunna utföras på en kö Skapa en tom kö Lägga till ett element sist i kön Ta bort ett element först i kön (elementets värde ska returneras) Konvertera kön till en lista a) Implementera en abstype för datatype kö med operationerna ovan b) Implementera (utanför abstype deklarationen) funktionen rude som tar en kö och ett värde och skapar en ny kö där det nya värdet finns framför de värden som fanns i kön. abstype a QUE = que of a list with val empty = que []; fun push (x,que k)=que (k@[x]); fun pull (que (x::xs))=(x,que xs); fun tolist (que k)=k; fun rude x que= foldr (fn (y,z)=>push(y,z)) push(x empty) (tolist que); Uppgift 2(4 poäng) Vilken typ har följande uttryck/funktioner? a) (op mod,true) (int*int->int)*bool b) fn x=>x a-> a UMEÅ UNIVERSITET 901 87 UMEÅ Tel.: 070-2378695 e-mail: johane@cs.umu.se
Tentamen På kursen: Programmering i ett funktionellt språk c) fun c list= map (fn (x,y)=> x) list; ( a* b) list-> a list d) fn x=>fn y=>(y+x+1) int->int->int Uppgift 3 (2+2=4 poäng) Vad gör nedanstående funktioner? Svara med en mening, jag är inte intresserad av detaljerna i hur den gör detta. a) val a= foldr (fn(x,y)=>if (x>0) then x::y else y) []; Filtrerar bort alla värden som är mindre är negativa ur en lista b) fun b l = let fun r(nil,acc) = acc r(h::t,acc)= r(t,h::acc) in r(l,nil) Vänder på en lista (samma som rev) Uppgift 4(4 poäng) En sträng som är balanserad med avseende på tecknen "(" och ")" har följande egenskaper: i. den innehåller lika många förekomster av både "(" och ")" ii. när man läser strängen från vänster till höger så är vid varje position i strängen antalet "(" större än eller lika med antalet ")". Till exempel är korrekta aritmetiska uttryck alltid balanserade med avseende på. "(" och ")", medan strängen "(a+b))*((c-d)" inte är balanserad eftersom den bryter mot villkor ii. Din uppgift är att konstruera en generell ML-funktion som tar två godtyckliga tecken och en sträng som parametrar, och returnerar ett booleskt värde som talar om ifall strängen är balanserad med avseende på dessa tecken. local fun check _ ~1=false check c1 c2 [] num= num=0 check c1 c2 (x::xs) num=if x=c1 then check c1 c2 xs (num+1) else if x=c2 then check c1 c2 xs (num 1 ) else check c1 c2 xs num; in fun balan c1 c2 str= check c1 c2 (explode str) 0 Uppgift 5 (4 poäng) Vi har under denna kurs använt oss av den funktionella programmeringsparadigmen. Jämför denna med den objektorienterade (som ni tittade på Java kursen) och den imperativa programmeringsparadigmen. 2(5)
Tentamen På kursen: Programmering i ett funktionellt språk I de funktionella språken så används rekursion för att åstadkomma upprepning, medan de imperativa och objektorienterade språken (främst) använder sig av iteration (loopar av olika slag tex for while osv) De funktionella språken har också högre ordningens funktioner som ett ganska centralt begrepp. Detta förekommer endast i mkt begränsad omfattning i de imperativa och objektorienterade språken (i vissa språk inte alls). Saker som polymorfism och lat evaluering är också vanliga. Funktioner i de funktionella språken liknar de som finns i matematiken (de har oftast inga sidoeffekter) De imperativa och objektorienterade språken så löser man problem genom att ange en sekvens av kommandon som ska köras av datorn. Man har variabler som är abstraktioner av minnesceller (till skillnad från de funktionella där man snarare har identifierare bundna till värden). De objektorienterade paradigmen är i stort sett bara en utveckling av den imperativa. Till de begrepp som fanns där har man lagt till begrepp som Klasser och objekt och arv, som förenklar återvändande av kod och inkapsling. Klasser finns för att försöka ge en bättre koppling mellan program och problemet man försöker lösa. (Kanske lite ostrukturerat, men stora delar av ovanstående bör iallafall finnas med) Uppgift 6 (2+4=6 poäng) Givet följande datatypsdefinition: datatype TREE= Empty Node of TREE *int *TREE a) Skriv ett uttryck som motsvarar trädet nedan. Node(Node(Node(Empty,4,Empty),2, Node(Empty,5,Empty)), 1,Node(Empty,3,Node(Empty,6,Empty))); b) I ett ordnat binärt träd kan det vara bra att ha en funktion remove med typen TREE->int->TREE för att ta bort ett visst värde ur trädet. Trädet skall fortfarande vara ordnat efteråt. Skriv funktionen remove. local fun find_min (Node(Empty,v,r))=v find_min (Node(l,v,r))=find_min l; fun remove_min (Node(Empty,v,r))=r remove_min (Node(l,v,r))=Node(remove_min l,v,r); in fun remove x Empty = Empty remove x (Node(l,v,r))=if x<v then Node(remove x l,v,r) else if x>v then Node(l,v,remove x r) else if r=empty then l else if l=empty then r else Node(l,find_min r, remove_min r); 3(5)
Uppgift 7(4 poäng) Tentamen På kursen: Programmering i ett funktionellt språk Givet följande funktor och två signaturer för att hantera sortering. Skapa en struktur för att sortera par av typen int*string. Endast det första delen av paret (heltalet) skall användas för att avgöra parets storlek (du måste använda dig av funktorerna och signaturerna nedan). Sorteringen skall ske i stigande ordning dvs mindre värden först. För att visa att du kan använda den nyskapade strukturen skall du också visa ett exempel där du sorterar en lista mha den nya strukturen (ta även med returvärdet). signature param_sig = sig type value_type; val order : value_type->value_type-> bool signature functor_sig = sig type value_type; val sort:value_type list->value_type list functor SORT(S: param_sig):functor_sig where type value_type=s.value_type= struct type value_type=s.value_type; (* fortsätter på nästa sida*) fun split []=([],[]) split [x]=([x],[]) split (x::y::ys)= let val (l1,l2)=split ys in (x::l1,y::l2) fun merge ([],[])=[] merge ([],lista)=lista merge (lista,[])=lista merge (x::xs,y::ys)=if S.order x y then x::merge(xs,y::ys) else y::merge(x::xs,ys) fun sort []=[] sort [x]=[x] sort xs= let val (l1,l2)=split xs in merge (l1,l2) structure SORT_PAIR: param_sig = struct type value_type=(int*string); fun order (x,_) (y,_)=x<y; structure mysort=sort(sort_pair); mysort.sort([(2, Hej ),(1, A )]); val it = [(1, "A"), (2, "Hej")] : (int * string) list 4(5)
Uppgift 8 (6 poäng) Tentamen På kursen: Programmering i ett funktionellt språk Förklara följande uttryck och ge exempel på en funktion av varje typ (förklara även varför just denna funktion tillhör denna typ) a) Högre ordningens funktion En funktion som tar en annan funktion som parameter och/eller ger en funktion som resultat. Tex map (se def. nedan) Denna tar både en funktion som parameter (f) och returnerar också en funktion om man bara ger den denna parameter. b) Partiell funktion Funktion som inte är definierad för alla värden som parametern till funktionen kan anta Tex fackultetsfunktionen (fac; se nedan) fun fac 0=1; fac n=n*fac (n-1); Resultatet av denna är ej definierad för negativa värden på n c) Partiellt applicerbar funktion Funktion som om man ger dess första parameter som resultat ger en funktion som tar nästa parameter Tex map Om denna får (bara) en funktion skickad till sig, så får man som resultat en funktion som tar en lista (och applicerar funktionen på alla element i denna) Uppgift 9(3p) Evaluera uttrycket map (fn x=>x*x) [1+2,2,3] steg för steg så långt det går. Visa varje steg i evalueringen. Hjälp: En definition av map att använda ovan (om ni ej kommer ihåg den) fun map f []=[] map f (x::xs)=f x::map f xs; map (fn x=>x*x) [1+2,2,3]=> map (fn x=>x*x) [3,2,3]=> (fn x=>x*x) 3:: map (fn x=>x*x) [2,3]=> 3*3:: map (fn x=>x*x) [2,3]=> 9:: map (fn x=>x*x) [2,3]=> 9:: (fn x=>x*x) 2:: map (fn x=>x*x) [3]=> 9::2*2:: map (fn x=>x*x) [3]=> 9::4:: map (fn x=>x*x) [3]=> 9::4:: (fn x=>x*x) 3:: map (fn x=>x*x) []=> 9::4:: 3*3:: map (fn x=>x*x) []=> 9::4:: 9:: map (fn x=>x*x) []=> 9::4:: 9:: []=>9::4 [9]=> 9:: [4,9]=>[9,4,9] 5(5)