Inleiding Functioneel Programmeren met Clean Functioneel Programmeren Gebaseerd
Inleiding Functioneel Programmeren met Clean
Functioneel Programmeren • Gebaseerd op het wiskundige functie begrip • Heel anders dan Mat. Lab, Java, etc • Geen assigment! • Uitgangspunt zijn expressies: 3 + 4*6 29 -12 -2021 2
Functies Een klein Clean programma module Voorbeeld import Std. Env // Naam programma // Standaard import Start = 6 * 7 Start is hoofdfunctie 6 * 7 is het resultaat van start het resultaat is altijd een expressie 29 -12 -2021 3
Functies Een programma met functie Start = kwadrateer 4 kwadrateer x = x * x Let op geen haakjes links van = ! If constructie: myabs x | x >= 0 = x | otherwise = ~x Let op: ~x = -x 29 -12 -2021 4
Functies Iets ingewikkelder: f x | x > 0 && x < 5 = 1 | x >= 5 && x < 10 = 2 | otherwise = 3 Functie met boolean resultaat kleiner. Dan 3 x = x < 3 kleiner. Dan 3 5 -> False kleiner. Dan 3 2 -> True 29 -12 -2021 5
Functie met where clause Nulpunten vierkantsvergelijking x 12 a b c = ((~b - wd) // (2*a), (~b + wd) // (2*a)) where wd = sqrt (b^2 - 4 * a * c) Where voor efficiency en leesbaarheid In where mag ook functie staan f a b = g b where g x = x + a 29 -12 -2021 6
Types Characters en Strings from. Char 'a' to. Char 97 "dit "het 34 + 29 -12 -2021 // -> 97 // -> 'a' is" +++ " een string" // plakken is een string" % (4, 5) // substring "is" is een string". [11] // element -> 's' getal is " +++ to. String 42 // int -> str to. Int "12" // str -> int 7
Lijsten: alle elementen van dezelfde soort! In FP talen zijn lijsten meest gebruikte opslag! [1, 2, 3, 6, 3, 9] // : : [Int] [True, False, True] // : : [Bool] ['d', 'i', 'c', 'k'] == ['dick'] // : : [Char] [] //(lege lijst) [4, 2, 6] !! 0 -> 4 [4, 2, 6] !! 2 -> 6 length [4, 2, 6] -> 3 [1, 2] ++ [3, 4] -> [1, 2, 3, 4] 29 -12 -2021 8
Standaard Functies op Lijsten remove. Members [4, 2, 3] [1, 2, 3, 4, 5, 6] -> [1, 5, 6] hd [1, 2, 3] -> 1 tl [1, 2, 3] -> [2, 3] take 3 [1, 2, 3, 4, 5] -> [1, 2, 3] drop 3 [1, 2, 3, 4, 5] -> [4, 5] Er geldt: take n xs ++ drop n xs == xs [2 : [3, 4]] -> [2, 3, 4] // 1 e element toevoegen [1. . 10] [1, 3. . 10] [7, 6. . 1] -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -> [1, 3, 5, 7, 9] -> [7, 6, 5, 4, 3, 2, 1] 29 -12 -2021 9
Functies op Lijsten [1. . ] take 10 [1. . ] -> [1, 2, 3, . . ] // oneindige lijst -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] sum [1, 2, 3, 4] prod [1. . 4] -> 10 -> 24 and [2<3, 4>9] or [2<3, 4>9] -> False -> True 29 -12 -2021 10
Lijstcomprehensies Handige notatie om snel een lijst te berekenen [2*x\ x <- [3, 4, 1, 6]] -> [6, 8, 2, 12] x <- xs noemen we een generator [x\ x <- [1. . 10]| x rem 2 == 0] -> [2, 4, 6, 8, 10] | x rem 2 == 0 noemen we een conditie [3*x\ x <- [1. . 10]| x rem 2 == 0] geeft [6, 12, 18, 24, 30] 29 -12 -2021 11
Lijstcomprehensies Meerdere generatoren achter elkaar geven geneste lus: [(x, y)\ x <- [1. . 3], y <- [7. . 8]] -> [(1, 7), (1, 8), (2, 7), (2, 8), (3, 7), (3, 8)] Alle Pythagorische drietallen met a, b, c kleiner dan 20 [(a, b, c) \ a <- [1. . 20], b <- [1. . 20], c <- [1. . 20]| a^2+b^2 == c^2] -> [(3, 4, 5), (4, 3, 5), (5, 12, 13), (6, 8, 10), (8, 6, 10), (8, 15, 17), (9, 12, 15), (12, 5, 13), (12, 9, 15), (12, 16, 20), (15, 8, 17), (16, 12, 20)] 29 -12 -2021 12
Tuples Voor groeperen elementen gebruiken we tuples (12, True) (‘a’, 12, [3, 4]) // : : (Int, Bool) // : : (Char, Int, [Int]) Tuples mogen elementen van verschillend type bevatten, maar zijn niet uitbreidbaar. fst (3, 4) snd (3, 4) -> 3 -> 4 Gebruik patronen in functies f (a, b, c) = b 29 -12 -2021 13
Zip Aan elkaar rijgen van lijsten zip ([1. . 4], [7. . ]) -> [(1, 7), (2, 8), (3, 9), (4, 10)] Lijsten hoeven niet even lang te zijn! Vaak heel handig in functie definities: elem n xs = hd [x\(x, m) <- zip(xs, [0. . ])|n==m] is. Sorted xs = and [x<=y\ (x, y)<-zip(xs, tl xs)] 29 -12 -2021 14
Typering Expressies en functies in Clean hebben een type 42 3. 14 “Een string” ‘a’ (12, True) [1, 2, 3] : : : Int Real String Char (Int, Bool) [Int] Types worden tijdens compileren gecontroleerd. Dit scheelt de programmeur veel debug werk! 12 + True 29 -12 -2021 -> foutmelding 15
Typering Functie types kunnen meestal automatisch worden afgeleid, maar het is netjes (maar niet verplicht) om ze zelf op te geven f : : Int -> Int f a b = a + b g : : Int -> Int g a = a + 1 29 -12 -2021 16
Currying en hogere orde Functies Functie met twee argumenten levert op 1 argument toegepast nieuwe functie van 1 argument op. Dit noemen we Currying. f : : Int -> Int f a b = a + b f 3 : : Int -> Int Bv map past een functie toe op alle elementen van een lijst (is een zgn hogere orde functie) map g [1. . 5] map (f 3) [1. . 5] 29 -12 -2021 -> [2, 3, 4, 5, 6] -> [4, 5, 6, 7, 8] 17
Anonieme functies In map passen we functie toe op alle elementen lijst. Het is ook mogelijk om functie in de map te definieren mbv een anonieme functie, bv: x -> x + 3 is anonieme versie van: f x = x + 3 Volgende regels zijn dus equivalent: map (x -> x + 3) [1. . 5] map f [1. . 5] Anonieme functie zijn vaak handig in gebruik 29 -12 -2021 18
Polymorfe Functies Voor veel functies op lijsten doet het type van de lijst er niet toe. Zo’n functie is polymorf. Het type geven we dan aan met een variabele: length : : [a] -> Int take : : Int [a] -> [a] Niet alleen functies op lijsten kunnen polymorf zijn: compose f g x = f (g x) compose : : (a -> b) (c -> a) c -> b 29 -12 -2021 19
Recursie Clean heeft geen herhalingsconstructies zoals while en for. In plaats daarvan gebruiken we recursie: fac : : Int -> Int fac 0 = 1 fac n = n * fac (n-1) length : : [a] -> Int length [] = 0 length [x: xs] = 1 + length xs is. Sorted 29 -12 -2021 : : [Int] [] [x: y: xs] -> Bool = True = x <= y && is. Sorted (y: xs) 20
Recursieve Lijstfuncties Twee lijsten concateneren concat : : [a] -> [a] concat [] ys = ys concat [x: xs] ys = [x : concat xs ys] zip zip : : [a] [b] -> [] ys xs [] [x: xs] [y: ys] 29 -12 -2021 [a, b] = [] = [(x, y) : zip xs ys] 21
Recursieve Lijstfuncties take : : Int [a] -> [a] 0 xs = [] n [] = [] n [x: xs] = [x : take (n-1) xs] drop : : Int [a] -> [a] 0 xs = xs n [] = [] n [x: xs] = drop (n-1) xs 29 -12 -2021 22
Recursieve Lijstfuncties take. While : : (a -> Bool) [a] -> [a] take. While f [] = [] take. While f [x: xs] | f x = [x : take. While f xs] | otherwise = [] drop. While : : (a -> Bool) [a] -> [a] drop. While f [] = [] drop. While f [x: xs] | f x = drop. While f xs | otherwise = xs 29 -12 -2021 23
The power of FP Newton’s methode voor nulpuntsbepaling Stap 1: numerieke afgeleide bepalen deriv : : Real (Real -> Real) Real -> Real deriv eps f x = (f (x+eps) - f x) / eps f x = x^2 – 3*x Start = deriv 0. 0001 f 2 29 -12 -2021 -> 3. 0000001 24
The power of FP Idee Newton 1. neem beginpunt x 1 2. bepaal raaklijn (x 1, f x 1): y = a*x + f x 1 3. snij raaklijn met x-as -> x 2: x 1 – (f x 1) / a 4. herhaal 1, 2, 3 met x 2 -> x 3 , etc Stap 2: snijpunt x-as van raaklijn - a*x 1 approx : : Real (Real -> Real) Real -> Real approx eps f x = x - (f x) / a where a = deriv eps f x 29 -12 -2021 25
The power of FP Herhalen herhaal : : (a -> Bool) (a -> a) a -> a herhaal cond f s | cond s = s | otherwise = herhaal cond f (f s) Pas net zo vaak f toe op s tot dat (cond s) True oplevert. Functie is algemener toepasbaar! herhaalex = herhaal c f (0, 0) where c (i, s) = i == 10 f (i, s) = (i+1, s+i) Wat is het resultaat ? 29 -12 -2021 26
The power of FP Nulpunts benadering newton : : Real (Real -> Real) Real -> Real newton eps f x = herhaal cond nieuwsnijpunt x where cond x = abs (f x) < eps nieuwsnijpunt x = approx eps f x Gebruiken dezelfde eps voor differentiëren als conditie. Voorbeeld: Start = newton 0. 0001 f f x = 3. 0*x + 6. 0 29 -12 -2021 8. 0 27
The power of FP Benadering wortel functie wortel : : Real -> Real wortel a = newton 0. 00001 f 3. 0 where f x = x*x-a nroot : : Real -> Real nroot n a = newton 0. 00001 f 3. 0 where f = x^n - a 29 -12 -2021 28
Nieuwe Types Maken • Clean heeft voorgedefinieerde types: – Int, Real, Bool, String, Char, [a], (a, b), etc • Gebuiker kan ook zelf types maken • Vergelijkbaar met andere programmeertalen • Enumeratieve types • Recursieve Types • Record Types 29 -12 -2021 29
Enumeratieve Types Opsomming van elementen : : Maand = Januari | Februari | Maart | April | Mei | Juni | Juli | Augustus | September | Oktober | November | December Functiedefinities gaan met pattern matching aantal. Dagen : : Maand -> Int aantal. Dagen Januari = 31 aantal. Dagen Februari = 28. . . 29 -12 -2021 30
Enumeratieve Types Meer voorbeelden : : Geslacht = Man | Vrouw Hoeft niet een pure opsomming te zijn. Mogen ook alternatieven zijn : : Temperatuur = Celsius Int | Fahrenheit Int koud (Celcius t) = t < 0 koud (Fahrenheit t) = t < 32 29 -12 -2021 31
Record Types Vergelijkbaar met klassen in Object georienteerde talen. Structs in C, Records in Pascal, etc. : : NAW = { , , , } naam adres woonplaats geslacht : : : : String Geslacht Aanmaken element: jmj = { , , , } 29 -12 -2021 naam adres woonplaats geslacht = = "Jan Martin" "KIM" "Den Helder" Man 32
Record Types Gebruik in functies. Verschillende manieren om te pattern matchen: get. Naam 1 {naam} = naam get. Naam 2 naw = naw. naam set. Adres naw a = {naw & adres = a} set. AW naw a w = {naw & adres = a, woonplaats = w} is. Man {geslacht = Man} = True is. Man _ = False 29 -12 -2021 33
Arrays • Worden minder vaak gebruikt in FP talen. • Lijsten zijn meestal goed genoeg. • Als alle elementen moeten worden afgelopen is lijst even goed als array • Alleen bij random access zijn arrays veel sneller • Arrays hebben vaste lengte itt lijsten arrayvb : : {Int} arrayvb = {1, 2, 3, 4, 5, 6} 29 -12 -2021 34
Arrays • Toegang elementen (random access) arrayvb. [3] • Wijzigen element in ayray {vbarray & [2] = 77, [3] = 88]} • Array comprohensies {a*2\ a <-: array} • Conversie van lijst naar array en omgekeerd ar 2 list : : {a} -> [a] ar 2 list array = [x\ x <-: array] list 2 array : : [a] -> {a} list 2 array list = {x\ x <- list} 29 -12 -2021 35
- Slides: 35