Presentation laddar. Vänta.

Presentation laddar. Vänta.

1 Mer om Nr 7 Rekursion, listor, typer och funktioner.

Liknande presentationer


En presentation över ämnet: "1 Mer om Nr 7 Rekursion, listor, typer och funktioner."— Presentationens avskrift:

1 1 Mer om Nr 7 Rekursion, listor, typer och funktioner

2 2 Mönstermatchning på listor av tuppler fun zip [] [] = [] | zip (x::xs) (y::ys) = (x,y) :: zip xs ys | zip _ _ = raise Zip local fun unzip1 (f,s) [] = (f,s) | unzip1 (f,s) ((x,y)::xys) = unzip1 (x::f,y::s) xys in val unzip = unzip1 (nil,nil) end Behålla ordningen på elementen i listan fun unzip [] = (nil,nil) | unzip ((x,y)::xys) = let val (f,s) = unzip xys in (x::f,y::s) end

3 3 Typuttryck Hur beskrivs en typ dvs hur ser typuttryck ut: Typvariabler: 'a, 'b, … Eqtypvariabler: ''a, ''b,... Konstanta typer: int, bool, real, string, unit Tuppler: type 1 * … * type n Funktioner: type 1 -> … -> type n Typfunktioner: type typefunct, type list Flera argument: (type 1,…,type n ) typefunct

4 4 Namngivna typer Motsvarigheten till namngivna värden är namngivna typer. Namnet har då exakt samma betydelse som den namngivna typen och de är utbytbara. Varför namnge typer? –Illustrativa namn. Vi kan använda ett namn som säger vad vi avser att värden av den typen ska betyda. –Kortare uttryck. En långt komplicerat typuttryck kan ges ett kortare namn

5 5 Exempel Istället för en tuppel med olika typer. (string * bool * (int * int)) list ger vi illustrativa namn åt de olika delarna type regnum = string type enter_or_exit = bool type hour = int type minute = int type time = hour * minute type entry = regnum * enter_or_exit * time type p_house = entry list fun report (ph : p_house) =... val report = fn : p_house -> …

6 6 Polymorfa typuttryck type 'a pair = 'a * 'a fun f ((x,y): 'a pair) = x f (3,4) => 3 f (4.0,3.0) => 4.0 f (true, 5) => TypeClash

7 7 Rekursionsformer Stack rekursiva funktioner –Varje anrop måste vänta in resultat av nästa rekursiva anrop, beräkningarna läggs på en stack. Ackumulerande rekursion –Ett ackumulerande argument används vid beräkningarna.

8 8 Svansrekursion Evalueringen av en funktionskropp behöver aldrig uppskjutas för att vänta på resultatet från nästa rekursiva anrop. Resultatet av en funktion är det direkta resultatet av ett rekursivt anrop. exception Last; fun last [ ] = raise Last | last [x] = x | last (x::xs) = last xs; val last = fn : 'a list -> 'a Ackumulerande rekursion är ofta (ej alltid) svansrekursiv.

9 9 Ömsesidig rekursion Flera funktioner som anropar varandra. Alla funktionerna måste definieras "samtidigt". fun even 0 = true | even n = odd (n-1) and odd 0 = false | odd n = even (n-1); > val even = fn:int -> bool and odd = fn:int -> bool

10 10 Flera rekursionsanrop Linjärrekursion: –Ett anrop ger upphov till ett nytt anrop. Dubbel rekursion –Ett anrop ger upphov till två nya anrop fun fib 0 = 0 | fib 1 = 1 | fib n = fib (n-1) + fib (n-2); > val fib = fn : int -> int map fib (fromto 0 10); > [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] : int list

11 11 Quicksort Välj ett element (första) dela upp listan element som är större än det valda och de som är mindre. Sortera de delarna och lägg sedan ihop dem. fun quick [] = [] | quick [x:int] = [x] | quick (x::xs) = let val small = filter (fn y => y <= x) xs val large = filter (fn y => y > x) xs in quick small @ [x] @ quick large end val quick = fn : int list -> int list

12 12 Nästlad rekursion En rekursiv funktionsapplikation "inuti" en annan. Ackermann's funktion fun ack 0 m = m+1 | ack n 0 = ack (n-1) 1 | ack n m = ack (n-1) (ack n (m-1)); val ack = fn : int -> int -> int ack 3 3; > val it = 61 : int ack 3 4; > val it = 125 : int ack 3 5; > val it = 253 : int ack 4 1; > val it = 65533 : int

13 13 Curried och uncurried En curried funktion är partiellt applicerbara. Dvs en funktion som kan ta "ett argument i taget". Tar ett argument och returnerar en ny funktion som tar nästa argument osv. Curried - fun add x y :int = x+y; > val add = fn: int -> (int -> int); Uncurried - fun plus (x,y):int = x+y; > val plus = fn:(int * int) -> int;

14 14 Omvandling Det är alltid möjligt att göra om en ”uncurried” funktion till ”curried” och vice versa. fun curry ff x y = ff (x,y); > val curry = fn: (’a * ’b -> ’c) -> ’a -> ’b -> ’c curry plus; > val it = fn: int -> int -> int curry plus 2 3; > val it = 5:int fun uncurry f (x,y) = f x y > val uncurry = fn : ('a -> 'b -> 'c) -> ('a * 'b) -> 'c uncurry add; > val it = fn : (int * int) -> int uncurry add (2,3); > val it = 5 : int

15 15 Operatorer uncurried ML:s operatorer är infixa, ”uncurried”. op gör en infix operator prefix op / ; val it = fn : real * real -> real op + (2,3); val it = 5 : int curry op+ 2 3; val it = 5 : int


Ladda ner ppt "1 Mer om Nr 7 Rekursion, listor, typer och funktioner."

Liknande presentationer


Google-annonser