Föreläsning 4 (och 5?) i programmeringsparadigm.

Relevanta dokument
Föreläsning 5 i programmeringsparadigm.

Föreläsning 4 (och 5?) i programmeringsparadigm.

Del : Funktionell programmering. I alla deluppgifterna, använd Haskell och skriv typen för de identifierare du definierar.

Funktionell programmering DD1361

DD1361 Programmeringsparadigm. Carina Edlund

Enjoy Vattenfallsmodellen i funktionella språk

Föreläsning 6 i programmeringsparadigm. Tips kring programmering i Haskell och kring labbarna.

Enjoy Vattenfallsmodellen i funktionella språk

Programkonstruktion och datastrukturer. Moment 9 Om högre ordningens funktioner. PKD 2010/11 moment 9 Sida 1 Uppdaterad

Introduktion till Haskell

Tentamensdag 2002-aug-20 Tentamen i Funktionell Programmering Skrivtid 5 h

Föreläsning 4 i programmeringsparadigm.

Föreläsning 7 i programmeringsparadigm. Ytterligare Högre ordningens funktioner: filter, foldr foldl. Hutton 7.2, 7.3 och 7.4.

LÖSNINGSFÖRSLAG TENTAMEN PROGRAMMERING I ETT FUNKTIONELLT SPRÅK ML, 5P

Kap9. Operatorn.. Hudak 9.4 sid 11. Fermats förmodan, eller Fermats stora sats säger att. xm + ym == zm har heltalslösningar om och endast om m == 2.

Nada KTH 2003 okt 23 Tentamen Programmeringsparadigm 2D1350 Skrivtid 5 h 8-13

Nada KTH 2004 jan 12 Tentamen Programmeringsparadigm 2D1350 Skrivtid 5 h 8-13

F6: Högre ordningens funktioner. Mönster för rekursion (1) Mönster för rekursion (1b) Mönster för rekursion (2) Högre Ordningens Funktioner

Nada Tentamensdag 2004 okt 18 Tentamen Programmeringsparadigm Skrivtid 5 h

Föreläsning 8. newtype Chess = Chess [(Square, Chessman)] -- data ist f newtype OK -- data istället för newtype krävs om >1 konstruerare.

TDDC74 Programmering: Abstraktion och modellering Tentamen, lördag 27 augusti 2016, kl 8 12

Föreläsning 9 i programmeringsparadigm. Paradigmöversikt, paradigmhistoria, paradigmgeografi. Se även föreläsning 1.

Föreläsning 5 i programmeringsparadigm. Tips kring programmering i Haskell och kring labbarna.

Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 2

Programkonstruktion och datastrukturer. Moment 9 Om högre ordningens funktioner. PKD 2011/12 moment 9 Sida 1 Uppdaterad

Dagens föreläsning Programmering i Lisp Fö 5

Våra enkla funktioner eller procedurer

Tentamen. Datalogi I, grundkurs med Java 10p, 2D4112, Lördagen den 30 november 2002 kl , salar E33, E34

Del : Paradigmer allmänt.

TDDC74 Programmering, abstraktion och modellering DUGGA 2

Programmering II (ID1019) :00-17:00

Dagens föreläsning Programmering i Lisp Fö 7. Sammanfattning funktionell programmering Exempel på funktionella programspråk

Föreläsning 8. Paradigmöversikt, paradigmhistoria, paradigmgeografi. Se även föreläsning 1.

Programmeringsmetodik DV1 Programkonstruktion 1. Moment 9 Om högre ordningens funktioner. PK1&PM1 HT-06 moment 9 Sida 1 Uppdaterad

Del : Paradigmer allmänt.

Kungliga Tekniska Högskolan Ämneskod 2D1370 Tentamensdag 2001-maj-31 Tentamen i Funktionell Programmering Skrivtid 4 h

Lambdas. (och fler design patterns) Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2017

Imperativ programmering. Föreläsning 2

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

TDIU01 - Programmering i C++, grundkurs

Men först: Några funktioner ur preluden. Introduktion till programmering. Uppgiften. Variationer av uppgiften. Föreläsning 4

Del : Funktionell programmering. I alla deluppgifterna, använd Haskell och skriv typen för de identifierare du definierar.

Introduktion till formella metoder Programmeringsmetodik 1. Inledning

TDDD78, TDDE30, 729A Introduktion till Java -- för Pythonprogrammerare

Övningsuppgifter kapitel 8

Föreläsning 6: Metoder och fält (arrays)

Föreläsning 3-4 Innehåll. Diskutera. Metod. Programexempel med metod

Omtentamen för TDA540 Objektorienterad Programmering. Institutionen för Datavetenskap CTH HT-17, TDA540. Dag: , Tid:

Föreläsning 3-4 Innehåll

TDDC74 Programmering: Abstraktion och modellering Dugga 2, , kl 17-19

Pythons standardbibliotek

Tentamen i. TDDC67 Funktionell programmering och Lisp

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

TDDC74 Programmering: Abstraktion och modellering Datortenta , kl 14-18

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

Två fall: q Tom sekvens: () q Sekvens av element: (a b c) ; (sum-rec '(2 4 6)) = 12. q Första elementet uppfyller vissa villkor: (2 a b c)

Rekursiva algoritmer sortering sökning mönstermatchning

MATLAB. Python. Det finns flera andra program som liknar MATLAB. Sage, Octave, Maple och...

KOMPLETTERANDE HEMTENTAMEN TDDB53

Tillämpad Programmering (ID1218) :00-13:00

Programmering II (ID1019) :00-12:00

I dag: Blockstruktur, omgivningar, problemlösning

F4. programmeringsteknik och Matlab

Imperativ programmering. Imperativ programmering konstruktioner i Lisp. Datastrukturer (kap ) arraystruktur poststruktur

Välkomna till DIT012 IPGO. Tyvärr en bug i Google Docs: Sidnummer stämmer inte alltid. Alla anteckningar börjar på sidan 1.

Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Tentamen i kurserna Beräkningsmodeller (TDA181/INN110) och Grundläggande Datalogi (TDA180)

Tentamen Programmeringsteknik II Inledning. Anmälningskod:

Tentamen Grundläggande programmering

Omtentamen: Tillämpad Programmering (ID1218) :00-13:00

Objekt-orienterat vs funktionellt Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Välkommen till. Datastrukturer, algoritmer och programkonstruktion. eller DOA

TDDD78, TDDE30, 729A Introduktion till Java -- för Pythonprogrammerare

TDDC30. Kursledning Kursledare: Jonas Lindgren. Labassistent: Jonas Lindgren Labassistent: Niklas Holma Labassistent: Erik Nilsson

Typkonvertering. Java versus C

Datatyper och kontrollstrukturer. Skansholm: Kapitel 2) De åtta primitiva typerna. Typ Innehåll Defaultvärde Storlek

TDP002 - Imperativ programmering

Övning2. Variabler. Data typer

Dagens föreläsning Programmering i Lisp. - Bindning av variabler (avs 14.6) fria variabler statisk/lexikalisk och dynamisk bindning

Programmering II (ID1019) :00-11:00

Föreläsning 10 Datalogi 1 DA2001. Utskrift på skärmen. Syntax. print( Hej ) Hur är det? Hej. print( Hej,end= ) print( Hur är det? ) HejHur är det?

2D1311 Programmeringsteknik för Bio1 och Bio2, vt 2003 Fiktivt prov På flervalsfrågorna är endast ett svar rätt om inget annat anges i frågan! Det rik

Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson

Laboration 1: Figurer i hierarki

TDDC74 Programmering: Abstraktion och modellering Datordugga 2 - exempel

Föreläsning 6: Introduktion av listor

Programmering I Tobias Wrigstad fredag, 2009 augusti 28

Generic type declarations. Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Tentamen Datastrukturer D DAT 035/INN960 (med mycket kortfattade lösningsförslag)

Obligatorisk uppgift 5

Outline. For. I istället för att följa det normala ordningen, man ändra den. I i Java får man inte göra hopp hur som helst

Multipel tilldelning. Introduktion till programmering D0009E. Föreläsning 6: Iteration. while-satsen. Kom ihåg. Snurror kontra rekursion

Det är principer och idéer som är viktiga. Skriv så att du övertygar rättaren om att du har förstått dessa även om detaljer kan vara felaktiga.

TDDC77 Objektorienterad Programmering

TDDC74 Programmering: Abstraktion och modellering Dugga 2, , kl 14-16

Senast. Idag. Icke-strikt evaluering. Strikt evaluering. Testa latheten! Lat evaluering. Plus och minus med lat evaluering. Testa latheten!

Beräkningsvetenskap föreläsning 2

Laboration: Whitebox- och blackboxtesting

Abstraktion. Abstraktion... Abstraktion... Abstraktion...

Transkript:

Föreläsning 4 (och 5?) i programmeringsparadigm. Högre ordningens funktioner på listor; funktioner som argument: map, filter. (Fokker 3.1.3, C&K p 37, 38) map -- förändra alla element i en lista på samma sätt. (i st f for-loopar). filter -- filtera (välj ut) en del element ur en lista. (i st f for-loopar). Exempel, vår kära power: power :: Int -> Int -> Int -- Om man kan map,[.. ] (i Prelude) power m n = product (map f [1..n]) --, n>0 ger 1 where f _ = m Listomfattning. (List comprehensions, Fokker 3.2.7) I stället för att använda map och filter kan man med listomfattning (List comprehension) skriva väldigt eleganta program, lätta att skriva och förstå. Några delar av Schack-labben blir ännu enklare att skriva med listomfattning än med map och filter. 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]] Exempel från Fokker Uttrycket [x*x x <- [1..10]] motsvarar let square x = x*x in map square [1..10]] eller med λ-notation (se nedan) map (\x -> x*x) [1..10]] Syntaxen påminner om matematikens syntax för mängder : {x*x x e N, 1 <= x, x <= 10} Även i listomfattningar kan man skriva villkor: map (\x -> x*x) [1..100], x <= 10] (Fånigt exempel) λ-notation (lamda-notation, anonyma funktioner). Fokker 2.3.4. Vi kan om vi vill definiera hjälpkonstanter, t ex i detta uttryck : kommunalskatt inkomst = skattesats * inkomst where skattesats = 0.30 -- skattesats definieras som 0.30. Ev globalt "skåp". Men om vi är för lata för att "döpa" 0.30 till skattesats så kan vi förstås helt enkelt skriva kommunalskatt inkomst = 0.30 * inkomst

Dvs i en definition namngivet begrepp kan ersättas med sin definition. Låt oss nu titta på mapf lista = map f lista where f i = 3*i + b b = 5 -- f definieras som en funktion med högerledet 3*i + b där i är parameter I en vanlig mattebok skulle en definition av f se ut så här f(i) = 3*i + b, vilket ju påminner om vår definition f i = 3*i + b. Men om vill kunna ersätta f i uttrycket mapf lista = map f lista kan vi ju inte bara skriva mapf lista = map (3*i + b) lista --- Fel!!!!!!!! eftersom (3*i + b) är ett uttyck men f är en funktion. I en sorts matematik som kallas λ-kalkyl skriver man definitonen av f som f = λi. 3*i + b Motsvarande sätt att definiera funktionen f går också att använda i funktionella språk: f = \i -> 3*i + b --- <namn> = <värde> som för konstanter (Teoretiskt sett "det riktiga sättet", det sätt vi använt hittills är en eftergift till konventionell matematik) mapf lista = map f lista where f = \i -> 3*i + b b = 5 -- f definieras som en funktion med högerledet 3*i + b där i är parameter Men om vi är för lata för att "döpa" vår funktion till f så kan vi förstås helt enkelt skriva mapf lista = map (\i -> 3*i + b) lista Dvs ett i en definition namngivet begrepp kan ersättas med sin definition. Exempel, vår kära power: power :: Int->Int->Int -- accumulerande lösningar med until, lamda power m n -- Fokker 2.3.2, Fokker 2.3.4 n<0 = error " second argument till power >= 0" otherwise = snd (until (\(i, _) -> ( i == n )) (\(i, acc) -> (i+1, acc*m) ) (0, 1))

För den som är intresserad av teori: Att i en definition namngivet begrepp alltid kan ersättas med sin definition är en mycket viktig egenskap hos matematik och funktionella språk. I imperativa språk gäller inte detta, trots att det borde vara en självklarhet, ett exempel i Java: static int x = 4; int y = f(x) * f(x) ; Efter att kört dessa två satser är inte y säkert samma värde som när man kört detta program static int x = 4; int z = f(x) int y = z * z; Låt t ex f ha denna definition static int f(int u) { int result = 2*u; x = 5; //sidoeffekt return result; } Sidoeffekter ställer lätt till med en massa elände och gör att man i imperativ och objektorienterad programmering måste tänka sig in i vad som händer vid körningen. Sammanhanget (contexten), vad som hänt under körningen och inte bara vad som står i programkoden, spelar ofta roll när man skall tolka något i ett imperativt språk. Ordningen mellan satser spelar (en mycket stor) roll i imperativa språk. Att skriva bra imperativa program innebär att använda minimalt med sidoeffekter (eller i OO använda sidoeffekter på ett kontrollerat sätt) och se till att så få begrepp som möjligt samtidigt är relevanta i något sammanhang. Betydelsen av en funktionsdeklaration i ett funktionellt språk beror inte på vad som händer vid en körnming. Funktionsdeklarationer kan stå i godtycklig ordning. Funktionella språk har inga sidoeffekter, programmeringen innebär att definiera begrepp, dvs lämpliga funktioner och datatyper (och typklasser). Bl a Haskell Curry arbetade med λ-kalkyl på 1930-talet, en gren av matematiken där λ-notationen är ett viktigt begrepp, dvs λ-kalkyl är äldre än datortekniken. Kärnan i funktionell programmering är helt enkelt λ-kalkyl. Haskell Curry har hedrats genom att hans förnamn har namngivit programspråket Haskell och hans efternamn givet namne på en viktig teknik för att skriva funktioner som behandlas i om en stund. Användbara funktioner; until. Fokker 2.3.2 En mängd användbara funktioner finns som redan betonats i Preluden, där de också är definierade, de allra flesta med några få rader Haskell. Att använda dessa funktioner är bekvämt, man slipper göra

ungefär samma sak gång på gång, programmering blir mindre tjatigt och programmeringen går ännu fortare, programmen blir kortare och programmering blir på "högre nivå", bekväm och lustfylld. Man kan naturligtvis själv också göra högre ordningens funktioner, och gör man dem bra (bl a så polymorfa som möjligt) så kan dom vara användbara gång på gång i en mängd olika sammanhang. Men många av dom högre ordningens funktioner som finns i Preluden är väldigt användbara. Ett exempel : until -- förvandla något gång på gång så länge något gäller (~loopar). I Prelude : until :: (a -> Bool) -> (a -> a) -> a -> a until p f x = if p x then x else until p f (f x) snyggare med vakter (tycker jag och Fokker) until p f x p x = x otherwise = until p f (f x) Obs. svansrekursiv. "loopar" (slinger, snurror) i imperativa språk kan programmeras med until, och många av våra lösningar med "ackumulering i parametrar" kan också lösas med until. De "imperativa programmeringsvariablerna" motsvaras av komponenterna i en tuppel, "<status>": Java : Haskell : while <not p> { until p f <status> <f > where p :: <statustyp> -> Bool } p <status> =.. - -funktion som blir True när vi skall sluta f :: <statustyp> -> <statustyp> f <status> =..- -funktion som beskriver "loopens kropp" Exempel, vår kära power: power :: Int -> Int -> Int -- accumulerande lösningar med until, power m n n<0 = error " second argument till power >= 0" otherwise = snd (until p f (0, 1)) where p (i, _) = ( i == n )) f(i, acc) = (i+1, acc*m) I Java : static int power (int m, int n) { //snurra, lokala variabler if (n < 0) { throw new RuntimeException("second argument till power >= 0"); } else { int acc = 1; for (int i = 0; i<n ; i = i+ 1) { acc = acc*m; } return acc; } } Alla sätt att resonera kan fångas med funktioner!

Högre ordningens funktioner, higer-order functions (HOF). Funktioner resultat: Currying. Fokker 2.2.1, 2.2.2, 2.2.3 Låt oss definiera add :: (Int, Int)->Int add (x,y) = x + y -- eller add = \ (x,y) -> x+ y add (3,5) blir 8 dvs vi säger att add har en parameter som är ett heltalspar och lämnar ett heltal som resultat. Detta påminner ju om hur vi skriver i matte brukar skriva add(x,y) = x + y, men det vanliga men egentligen felaktiga språkbruket är att add "är en funktion av två variabler", men Funktioner har alltid bara en enda parameter. När funktioner används har de alltid bara ett enda argument. Låt oss definiera plus :: Int -> (Int->Int) (plus x) y = x + y -- eller plus = \ x -> (\y -> x + y) (plus 3) 5 blir 8 -- ganska löjligt, enklare((+) 3) 5, 3+5 eftersom plus = (+) dvs det korrekta sättet att beskriva plus är att plus har en parameter x som är ett par heltal och lämnar som resultat en anonym funktion (\y -> x + y). Detta syns tydligare om vi läser definitionen av plus med λ-notation. När vi t ex gör (plus 3) får vi som resultat funktionen (\y -> 3 + y). Denna funktion kan nu appliceras på t ex 5, dvs (\y -> 3 + y) 5 vilket blir 8. När funktioner används har de alltid bara ett enda argument. Är resultatet en funktion kan resultatet användas på ytterligare ett argument osv. Funktionsapplikation binder till höger, dvs f g x betyder (f g) x. -> i typutryck binder till höger, dvs Int -> Int ->Int betyder Int -> (Int ->Int). Alltså kan vi skriva på detta sätt plus :: Int -> Int->Int plus x y = x + y -- eller plus = \ x -> (\y -> x + y) plus 3 5 blir 8 vilket vi gjort hela tiden, men inte förklarat egentligen varför vi kan skriva på detta sätt. plus kalls en "a curried funtion", på svenska en partiellt applicerbar funktion. I detta exempel har vi visat att en funktion med ett par som parameter (add) har en motsvarande "curried" funktion (plus), och på liknade sätt kan man resonera för triplar och tupler i allmänhet.

Det är ingen nackdel att använda sådana funktioner i stället för tupler. Fördelen är att man kan ha användning av "mellanfunktionerna". När man använder t ex plus med endast ett argument gör man en partiell applikation. (Fokker kallar det partiell parametrisering). Även operatorer kan partiellt appliceras, vilket kallas operator snitt (operator sections). T ex är följande uttryck olika sätt att skriva samma sak, värdet blir alltid [2, 4, 6] : let f x = 2*x in map f [1, 2, 3] let f = \x -> 2*x in map f [1, 2, 3] map f (\x -> 2*x) [1, 2, 3] map (2*) [1, 2, 3] map (*2) [1, 2, 3] Ett exempel från Schack-labben, steg 3b Polygongraphics ("kanske kusens svåraste uppgift"): Vi har en definitionen vektoradditon från Vector med typen : vadd :: Vector -> Vector -> Vector Antag att vi har en lista med polygonkoordinater poly::[vector] (dvs en pjäs utseende) som skall flyttas till något ställe at::vector (dvs en schackruta). Vi skulle kunna ha användning för något som.. map movedtosq poly... where movedtosq = vadd at -- enklare -- movedtosq coord = vadd at coord -- sämre men det är bekvämt, enklast och bäst att slippa definiera movedtosq.. map (vadd at) poly... vilket är möjligt tack vare att vadd är partiellt applicerbar. Ytterligare exempel från steg 3 i schack- labben: På analogt sätt kan man ha glädje av att multiplikation med skalär mscal :: Float -> Vector -> Vector är partiellt applicerbar när vi skall skala polygoner. Funktionssammansättning. Fokker 2.3.3 Uttrycket f ( g x ) kan skrivas som (f. f) x eller let h = f. g in h x. Exempel: map f (map g (map h lista)) skrivs lämpligen map (f.g.h) lista. (man slipper gå igenom listan gång på gång)

Ett exempel från Schack-labben, steg 3b Polygongraphics ("kanske kusens svåraste uppgift"): Antag att vi har en lista med koordinater (en polygon till exempel) flyttas och skalas och räknas om till pixlar. Skrivs lämpligen som map ( tillpixlarfunktion. flyttfunktion. skalfunktion) lista. Om flyttfunktionen och skalfunktionen talade vi ju om i föregående avsnitt. Märk också likheten mellan Haskells. och i Unix för att göra "pipes". Vad vi nu har gått igenom i Fokker. Nästan allt i kapitel 1, 2, och 3 hoppas jag nu är förståeligt. Det som vi inte har behandlat än är lat evaluering och oändliga listor 3.2.4, 3.25, 3.26. Man behöver inte förstå detta för att klara schacklabben. Lat evaluering och oändliga listor möjliggör dock att det är möjligt att programmera ännu elegantare och effektivare i Haskell, så jag hoppas kunna prata om detta på någon av de sista Haskell-förläsningarna. Vad vi nu har gått igenom i C&K. Nästan allt i kapitel 1, 3, 4, 5, 8, 10. Vi har kvar kapitel 7. Övriga kapitel ej i denna kurs. Hur man ritar bilder m m. Inför Steg 3 och 4 i schacklabben Se Labbhäftet sid 28 <= sid <= 34

Gamla tentatal: 5 a) Definiera en datatyp för binära träd med information i "löven". b) Antag att löven är funktioner. Skriv en funktion app som kan applicera lövens funktioner på ett givet argument. Ange typen för app. c) Skriv en funktion sumtree som summerar alla värden i ett lövträd med heltal i löven. Ledning : Ett delvis skämtsamt exempel på användning av deklarationerna i a), b( och c) (träden ritade på botaniskt i stället för datalogiskt sätt, rötterna nedåt) : \m -> 2* m*m + 3 \m -> 7*m + 15 \m -> 10*m + 7 Vår. Ett äppelträd mytree. Olika äppelsorter inympade. Funktionerna anger hur tunga (i g) tre äpplen blir som funktion av tiden (i månader). 90 57 67 Höst. 6 månader senare. Vikt för äpplenen på träden. app 6 mytree 214 Skördens vikt. sumtree (app 6 mytree)

module Appletree where -- på /info/progp02/haskelllectures/f5/appletree.hs data LeafTree a = Leaf a Node (LeafTree a) (LeafTree a) -- a) deriving Show app :: a -> LeafTree (a->b) -> LeafTree b -- b) app x (Leaf f) = Leaf (f x) app x (Node left right) = Node (app x left) (app x right) sumtree :: LeafTree Int -> Int -- c) sumtree (Leaf i) = i sumtree (Node left right) = sumtree left + sumtree right mytree :: LeafTree (Int -> Int) mytree = Node (Leaf (\m -> 10*m+7)) (Node (Leaf (\m -> 2*m*m+3*m)) (Leaf (\m -> 7*m+15))) {- -} Appletree> app 6 mytree Node (Leaf 67) (Node (Leaf 90) (Leaf 57)) Appletree> sumtree (app 6 mytree) 214 4 Skriv en funktion occurestimes n som lämnar som resultat en lista som innehåller de element som förekommer minst n gånger i list med anropet occurestimes n list. Exempel: occurestimes 2 [, "a", "hej", "Luleå", "a", "b", "hej"] ger svaret ["hej, "a"] occ [] = [] --Tal 4 på tentan occ (x:xs) = add x (occ xs) -- på /info/progp02/haskelllectures/f5/appletree.hs add x [] = [(x, 1)] add x ((y,n):ys) x == y = (x, n+1): ys otherwise = (y, n) : add x ys occurstimes m list = [x (x, n) <- occ list, m == n] {- occ :: Eq a => [a] -> [(a, Int)] occ = foldr add []...> occurstimes 2 ["a", "hej", "Lul", "a", "b", "hej"] ["hej","a"] -}

Quicksort i Haskell: module Quicksort where -- på /info/progp02/haskelllectures/f5/quicksort.hs qsort :: Ord a => [a] -> [a] qsort [] = [] qsort (x:xs) = qsort (filter (<=x) xs) ++ [x] ++ qsort (filter (x<) xs) {- Körning : :s +ts Quicksort> qsort [1,23, 14, 5, 8, 2, 14] [1,2,5,8,14,14,23] (469 reductions, 642 cells) -} {- qsort :: Ord a => [a] -> [a] qsort [] = [] qsort (x:xs) = qsort small ++ [x] ++ qsort large where (small, large) = foldl dir ([], []) xs dir -- (332 reductions, 594 cells) -} (sm, la) y y <= x = (y:sm, la) otherwise = (sm, y:la) Ett försök att motbevisa Fermats stora sats: --på /info/progp02/haskelllectures/f5/quicksort.hs triples = [ (x, y, z) x <- [1.. ], y <- [x..3], z <- [x..3]] fermat n = [ (x, y, z) x <- [1..20], y <- [x.. 20], z <- [x..20], x<=y, z^n == x^n + y^n] fermata n = [ (x, y, z) p <- [2..], x <- [1..p], y <- [x.. p], z <- [x..p], x<=y, z^n == x^n + y^n] fermatb n = take 1 [ (x, y, z) p <- [2..], x <- [1..p], y <- [x.. p], z <- [x..p], x<=y, z^n == x^n + y^n] fermatstorasats = [ ("n = " ++ show n, fermatb n) n <- [2..]] {-...> fermatstorasats [("n = 2",[(3,4,5)]),("n = 3",{Interrupted!} Inget motbevis än...