1 / 38

Högre ordningens listfunktioner nr 6

Högre ordningens listfunktioner nr 6. Ackumulerande parametrar Map, filter reduce. Ackumulerande parametrar. En parameter för att skicka tillfällig information mellan olika rekusions steg i en rekursiv funktion Varför: Lagra tillfälliga värden och bära delresultat För att hantera tillstånd

shanon
Download Presentation

Högre ordningens listfunktioner nr 6

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Högre ordningens listfunktionernr 6 Ackumulerande parametrar Map, filter reduce

  2. Ackumulerande parametrar • En parameter för att skicka tillfällig information mellan olika rekusions steg i en rekursiv funktion • Varför: • Lagra tillfälliga värden och bära delresultat • För att hantera tillstånd • Kontrollera rekursion.

  3. Lagra tillfälliga värden • Största elementet i en lista givet det hittills största fun max1 bsf [] = bsf : int | max1 bsf (x::xs) = if x > bsf then max1 x xs else max1 bsf xs > val max1 = fn : int -> int list -> int • Om det finns minst ett element i listan kan vi hitta det största, för en tom lista blir det ett undantag exception Max > exception Max fun max (x :: xs) = max1 x xs | max [] = raise Max > val max = fn : int list -> int

  4. Test max [1,4,2,6,5,7,2] ==> max1 1 [4,2,6,5,7,2] ==> max1 4 [2,6,5,7,2] ==> max1 4 [6,5,7,2] ==> max1 6 [5,7,2] ==> max1 6 [7,2] ==> max1 7 [2] ==> max1 7 [] ==> 7 - max []; • uncaught exception Max

  5. Lagra delresultat • Summera heltalen i en lista, lagra delresultaten i en parameter. Antag att alla värden i början är summerade i en parameter, tag sedan hand om resten av listan fun suma (s:int) (x::xs) = suma (s+x) xs | suma s [] = s > val suma = fn : int -> int list -> int • För att summera en lista låt delsumman vara noll till att börja med fun sumacc xs = suma 0 xs val sumacc = suma 0 > val sumacc = int list -> int

  6. sum [1,2,3,4] ==> 1 + sum [2,3,4] ==> 1 + (2 + sum [3,4] ==> 1 + (2 + (3 + sum [4]) ==> 1 + (2 + (3 + (4 + sum []))) ==> 1 + (2 + (3 + (4 + 0))) ==> 1 + (2 + (3 + 4)) ==> 1 + (2 + 7) ==> 1 + 9 ==> 10 sumacc [1,2,3,4] ==> suma 0 [1,2,3,4] ==> suma (0+1) [2,3,4] ==> suma (1) [2,3,4] ==> suma (1+2) [3,4] ==> suma (3) [3,4] ==> suma (3+3) [,4] ==> suma (6) [4] ==> suma (6+4) [] ==> suma (10) [] ==> 10 Jämförelse mellan sum och sumacc

  7. Hantera tillstånd • Ett tillstånd som förändras vid varje rekursivt anrop hanteras av en parameter. Tillståndet används för att beräkna slutresultatet. fun fname' state [] = MAKERESULT state | fname' state (x::xs) = fname' (TRANSFORMSTATE state x) xs val fname = fname' START_STATE

  8. Exempel: • Snittpris per enhet i ett lager beroende på antal av varje enhet fun average' (ta, tp) [] = tp / real ta | average' (ta, tp) ((a,p) :: aps) = average' (ta + a,tp + real a * p) aps > val average' = fn : int * real -> (int * real) list -> real val average = average' (0, 0.0) > val average = fn : (int * real) list -> real average [(50,23.0),(100,12.0),(67,9.0)]; > val it = 13.6082949308756 : real

  9. Kontrollera rekursion • Motsvarar loop-index, t ex en räknare för att avgöra hur många rekursiva anrop som skall göras. • Beräkna xn fun power x 0 = 1.0 | power x n = x * power x (n-1) > val power = fn : real -> int -> real

  10. Generell upprepning fun iter f 0 s = s | iter f n s = iter f (n-1) (f s) > val iter = fn : ('a -> 'a) -> int -> 'a -> 'a • Beräkna xn fun power x n = iter (fn y => x * y) n 1.0 > val power = fn : real -> int -> real power 7.0 12; > 1.38413E+10 : real

  11. twice igen! fun twice f = iter f 2 twice sq n ==> iter sq 2 n ==> iter sq 1 (sq n) ==> iter sq 0 (sq (sq n)) ==> sq (sq n)

  12. Inkapsling • Ett stor program bör delas in i enheter som är så oberoende av varandra som möjligt. • Från en sådan enhet bör endast de viktiga bitarna vara synliga utåt. De bitar som ska användas i andra delar av programmet. • De delar som endast används i enheten bör inte vara synliga utifrån. • Den som använder enheten ska inte behöva sätta sig in i detaljerna i hur enheten fungerar, utan enbart vilken effekt de synliga delarna har.

  13. Lokala deklarationer i ML • Den slutliga funktionen anropar ofta flera hjälpfunktioner för att lösa problemet. Dessa kan paketeras ihop och blir synliga endast för huvudfunktionen men inte utanför. local declarations1 in declarations2 end • Deklarationerna i declarations1 är endast synliga fram till end i deklarationen.

  14. Exempel local fun suma (s:int) (x::xs) = suma (s+x) xs | suma s [] = s in val sumacc = suma 0 end val sumacc = fn : int list -> int

  15. Lokala deklarationer i uttryck • Man kan ge namn åt tillfälliga värden inuti uttryck, det kan vara konstanta värden men också värden beroende av parametrar eller beräkningar som förekommer på flera ställen. let declarations in expression end • Värdet av lokalt deklarerade namnet är synligt endast fram till end i uttrycket. • Värdet av hela let-uttrycket är värdet av uttrycket expression.

  16. Exempel let val x = 10 in 2*x*x end; > val it = 200:int

  17. Ekvationslösning • Lösning av 2:a-gradsekvation (ax2 + bx + c = 0) exception Solve fun solve a b c = let val p = b*b -4.0*a*c in if p >= 0.0 then ((~b+sqrt p)/(2.0*a),(~b-sqrt p)/(2.0*a)) else raise Solve end; > val solve = fn: real->real->real-> (real * real) solve 1.0 2.0 ~3.0; val it = (1.0,~3.0) : real * real

  18. Sekvenser • En lista med kvadraten på alla tal mellan 1 och n [sq 1, sq 2, sq 3, … , sq n] • Först en funktion som genererar en lista med kvadraten på alla tal mellan m och k. fun sqlist1 m k = if m > k then [] else sq m :: sqlist1 (m+1) k val sqlist1 = fn : int -> int -> int list • Den används för att skapa en funktion från 1 till n val sqlist = sqlist 1

  19. Med lokala deklarationer local fun sqlist1 m k = if m > k then [] else sq m :: sqlist1 (m+1) k in val sqlist = sqlist1 1 end > val sqlist = fn : int -> int list sqlist 10; > val it = [1,4,9,16,25,36,49,64,81,100] : int list

  20. Vända på en lista • Att vända på en lista kan ses som att hela tiden flytta första elementet till en annan lista. • Jämför med att flytta böckerna i en hög en efter en till en ny hög. Ordningen i den nya högen kommer att vara den motsatt mot ursprungliga högen. local fun rev1 rlsf [] = rlsf | rev1 rlsf (x::xs) = rev1 (x::rlsf) xs in val rev = rev1 [] end val rev = fn : 'a list -> 'a list

  21. Exempel rev [1,2,3] ==> rev1 [] [1,2,3] ==> rev1 [1] [2,3] ==> rev1 [2,1] [3] ==> rev1 [3,2,1] [] ==> [3,2,1]

  22. Map • Ofta vill man utföra samma operation f på alla element i en lista • Givet: [x1, x2, …, xn] och en funktion f • Resultat: [f x1, f x2, …, f xn] • Kvadraten på alla heltal i en lista fun sqs [] = [] | sqs (x::xs) = sq x :: sqs xs • Denna form kan generaliseras fun map _ [] = [] | map f (x::xs) = f x :: map f xs val map = fn : ('a -> 'b) -> 'a list -> 'b list

  23. Utvidgning • Map kan ses som en utvidgning av en funktion från att gälla på enstaka värden till att gälla för listor av sådana värden. sq : int -> int map sq : int list -> int list floor : real -> int map floor : real list -> int list

  24. Exempel sqs [2,4,6] ==> map sq [2,4,6] ==> sq 2 :: map sq [4,6] ==> 4 :: map sq [4,6] ==> 4 :: sq 4 :: map sq [6] ==> 4 :: 16 :: map sq [6] ==> 4 :: 16 :: sq 6 :: map sq [] ==> 4 :: 16 :: 36 :: map sq [] ==> 4 :: 16 :: 36 :: [] ==> [4,16,36]

  25. Filter • Om man vill plocka bort vissa element från en lista givet något villkor, så kan man gå igenom listan och endast behålla de som uppfyller villkoret. • Behåll endast de jämna talen fun even n = n mod 2 = 0 val even = fn : int -> bool fun evens [] = [] | evens (x::xs) = if even x then x :: evens xs else evens xs val evens = fn : int list -> int list

  26. Generalisera • Abstrahera ut villkorsfunktionen (predikatet) fun filter _ [] = [] | filter p (x::xs) = if p x then x :: filter p xs else filter p xs val filter = fn : ('a -> bool) -> 'a list -> 'a list val evens = filter even

  27. Exempel evens [1,2,3,4] ==> filter even [1,2,3,4] ==> if even 1 then 1 :: filter even [2,3,4] else filter even [2,3,4] ==> filter even [2,3,4] ==> if even 2 then 2 :: filter even [3,4] else filter even [3,4] ==> 2 :: filter even [3,4] ==> 2 :: (if even 3 then 3 :: filter even [4] else filter even [4]) ==> 2 :: filter even [4] ==> 2 :: (if even 4 then 4 :: filter even [] else filter even []) ==> 2 :: 4 :: filter even [] ==> 2 :: 4 :: [] ==> [2,4]

  28. Primtal fun fromto n m = if n > m then [] else n :: fromto (n+1) m val fromto = fn : int -> (int -> int list) fun divides n m = m mod n = 0 val divides = fn : int -> (int -> bool) fun sieve [] = [] | sieve (x::xs) = x :: sieve (filter (not o divides x) xs) val sieve = fn : int list -> int list fun primes m = sieve (fromto 2 m) val primes = fn : int -> int list - primes 30; > val it = [2,3,5,7,11,13,17,19,23,29] : int list

  29. Ordnade listor • Det är vanligt att arbeta med ordnade listor. • För att kontrollera att en lista är ordnad fun iorder [] = true | iorder [(x:int)] = true | iorder (x1::x2::xs) = x1 <= x2 andalso iorder (x2::xs) val iorder = fn : int list -> bool

  30. Exempel iorder [1,3,5,6] ==> 1 <= 3 andalso iorder [3,5,6] ==> true andalso iorder [3,5,6] ==> iorder [3,5,6] ==> 3 <= 5 andalso iorder [5,6] ==> iorder [5,6] ==> 5 <= 6 andalso iorder [6] ==> iorder [6] ==> true

  31. Generaliserad ordning • Det som gör iorder specifik för heltal är "<=" om man abstraherar den få man en ordningskontroll för listor som är generell fun order _ [] = true | order _ [x] = true | order p (x1::x2::xs) = p x1 x2 andalso order p (x2::xs) val order = fn : ('a -> 'a -> bool) -> 'a list -> bool fun sle (x:string) y = x <= y val iorder = order (fn (x:int) => fn y => x <= y) val sorder = order sle

  32. Insättning i en ordnad lista • Om listan är ordnad med stigande värden så förblir den ordnad om jag sätter in ett element före det första element som är större än element som jag vill sätta in. fun inserti (v:int) [] = [v] | inserti v (x::xs) = if v <= x then v :: x :: xs else x :: inserti v xs val inserti = fn : int -> int list -> int list

  33. Generaliserad insättning • Om jag ersätter jämförelsen med en funktion p som avgör vilket värde som är mindre, får jag en generell insättningsfunktion. fun insert _ v [] = [v] | insert p v (x::xs) = if p v x then v :: x :: xs else x :: insert p v xs val insert = fn:('a->'a->bool)->'a->'a list->'a list

  34. Specialicering val inserti = insert (fn (x:int) => fn y => x <= y) val inserti = fn : int -> int list -> int list val inserts = insert sle val inserts=fn:string->stringlist->stringlist fun pairle ((x1:int),(y1:int)) (x2,y2) = x1 <= x2 orelse (x1 = x2 andalso y1 <= y2) val pairle = fn : int * int -> int * int -> bool val insertp = insert pairle val insertp = fn:int*int->(int*int)list->(int*int)list

  35. Insertion sort • Ta ut första elementet ur listan, sortera resten av listan och sätt sedan in det första elementet (i ordning) i den sorterade listan. fun isort [] = [] | isort (x::xs) = inserti x (isort xs) val isort = fn : int list -> int list • Generaliserar över insättningsfunktionen. fun sort insert [] = [] | sort insert (x::xs) = insert x (sort insert xs) val sort = fn : ('a -> 'b list -> 'b list) -> 'a list -> 'b list

  36. Specialisering • Specialicera för olika typer val isort = sort inserti val isort = fn : int list -> int list val ssort = sort inserts val ssort = fn : string list -> string list val psort = sort insertp val psort = fn : (int * int) list -> (int * int) list isort [2,5,1,7,4,9,2,4]; val it = [1,2,2,4,4,5,7,9] : int list

  37. Reducering/Folding • Att reducera värdena i en lista till ett värde. fun add (x:int) y = x + y fun sum [] = 0 | sum (x::xs) = add x (sum xs) fun concat s1 s2 = s1^s2 fun concs [] = "" | concs (x::xs) = concat x (concs xs) • Generalisera funktionen och resultatet för tomma listan fun reduce f b [] = b | reduce f b (x::xs) = f x (reduce f b xs) valreduce=fn:('a->'b->'b)->'b->'alist->'b

  38. Specialicera val sum = reduce add 0 val sum = fn : int list -> int val concs = reduce concat "" val concs = fn : string list -> string fun sort insert = reduce insert [] val sort = fn : ('a->('blist->'blist))->('alist->'blist) fun cons x xs = x::xs val cons = fn : 'a -> ('a list -> 'a list) fun map f = reduce (cons o f) [] val map = fn : ('a -> 'b) -> ('a list -> 'b list)

More Related