Functies definiëren Door combinatie van standaardfuncties fac :: Int Int fac n = product [1..n] oneven :: Int Bool oneven n = not (even n) negatief :: Int Bool negatief n = n < 0 Functies uitrekenen Met de interpreter module Stat where fac n = product [1..n] H:\> hi > :l Stat > fac 6 720 Met de compiler module Stat where fac n = product [1..n] main = fac 6 H:\> helium Stat.hs H:\> lvmrun Stat 720 Gevallen onderscheiden abs :: Int Int abs x | x>=0 | x<0 = x = -x “guards” Herhalen fac :: Int Int fac n | n==0 | n>0 graag zonder product te gebruiken = 1 = n * fac (n-1) “recursie” Lijst-patronen null :: [Int] Bool null [ ] = True null (x:xs) = False head :: [Int] Int head (x:xs) = x tail :: [Int] [Int] head (x:xs) = xs Zelftest Definieer de recursieve functie sum met patronen met gevalsonderscheid d.m.v. guards sum :: [Int] Int sum [ ] = 0 sum (x:xs) = x + sum xs sum :: [Int] Int sum xs | null xs = 0 | True = head xs + sum (tail xs) Quiz (basisschool) prioriteitsregel 5+3*2 16 11 associatief 5+3+2 10 10 links-associatief 55 -- 33 - 2 0 4 rechts-associatief 5^3^2 1252 59 machtsverheffen Quiz (logica) associatief FTF F F associatief FTF T T rechts-associatief FF F TT F T implicatie Quiz (Helium) los element op kop van lijst rechts-associatief associatief x : y : zzs x ++ y ++ z lijsten samenvoegen Quiz (Helium) toepassen van een functie links-associatief links-associatief map y z [1,2,3] mapf fac boven nn k boven Partieel parametriseren Stel: En dan: plus :: Int Int Int plus x y = x + y drieMeer :: Int Int drieMeer = plus 3 > map drieMeer [1, 2, 3, 4, 5] [4, 5, 6, 7, 8] Partieel parametriseren Omgekeerd: drieMeer = plus 3 drieMeer :: Int Int En dus: rechts-associatief plus :: Int (Int Int) plus :: Int Int Int “Curry-ing” Type f :: Int Bool String Aanroep > f 7 True “hoi” rechts-associatief links-associatief zonder haakjes! Currying Schönfinkelin g? Haskell B. Curry (1900-1982) Grundlagen der kombinatorischen Logik (1930) M. Schönfinkel Über die Bausteine der mathematischen Logik (1924) Currying en map > map fac [1, 2, 3, 4, 5] [1, 2, 6, 24, 120] > map (plus 3) [1, 2, 3, 4, 5] [4, 5, 6, 7, 8] > map ((*) 2) [1, 2, 3, 4, 5] [2, 4, 6, 8, 10] Hogere-ordefuncties Functie met een functie als parameter map filter Functie met een functie als resultaat inverse afgeleide elke functie met >1 parameter! Hogere-ordefuncties Een lijst langs lopen en met elk element iets doen map Een lijst langs lopen en sommige elementen selecteren filter map en filter doe dit overal > map even [1, 2, 3, 4, 5, 6] [False, True, False, True, False, True] > filter even [1, 2, 3, 4, 5, 6] [2, 4, 6] pak alleen deze Publieksvraag Schrijf een functie kleintjes die getallen van een lijst oplevert die kleiner zijn dan 10 kleintjes :: [Int] [Int] (>) 10 x 10>x x<10 kleintjes xs = filter ((>)10) xs ook partieel geparametriseerd! Definitie van map Geef een recursieve definitie: map :: (ab) [a] [b] map f [ ] = [] map f (x:xs) = f x : map f xs Definitie van filter Geef een recursieve definitie, en gebruik guards voor gevalsonderscheid filter :: (aBool) [a] [a] filter p [ ] = [] filter p (x:xs) | p x = x : filter p xs | True = filter p xs Een ander soort lijst-functies product :: [Int] Int product [ ] = 1 product (x:xs) = x * product xs and and and :: [Bool] Bool [] = True (x:xs) = x && and xs sum sum sum :: [Int] Int [] = 0 (x:xs) = x + sum xs Universele “lijst-totalisator” foldr :: (aaa) zo combineren a [a] a neutrale waarde foldr (#) e [ ] = e foldr (#) e (x:xs)= x # foldr (#) e xs Had dat eerder gezegd... Als foldr de generalisatie is van sum, product, en and .... .... dan zijn sum, product, en and speciale gevallen van foldr product and sum or = = = = foldr foldr foldr foldr (*) 1 (&&) True (+) 0 (||) False Hoger-ordefuncties op lijsten Doorloop een lijst en ... [a] [b] filter :: (aBool) [a] [a] map :: (ab) doe dit pak deze foldr :: (aaa) a [a] a combineer zo Andere hogere-ordefuncties until :: (aBool) (aa) a a totdat dit geldt doe dit begin hiermee filter p f x | p x = x | True = until p f (f x) > until ((<)1000) ((*)2) 1 1024 Andere hogere-ordefuncties (.) :: (bc) (ab) (a c)c a begin hiermee doe dit en dan dat (.) g f x = g (f x) > map (not . even) [1, 2, 3, 4, 5, 6] [1, 3, 5] Partieel parametriseren > map (plus 5) [1 .. 5] [6, 7, 8, 9, 10] > until ((<)1000) ((*)2) 1 1024 > filter (not . even) [1 .. 5] [1, 3, 5] Partieel parametriseren > map f [1 .. 4] where f x = x*x + 3*x + 2 [6, 12, 20, 30] ) [1 .. 4] > map ( \ x x*x+3*x+2 f [6, 12, 20, 30] Lambda-expressies expressie waar x vrij in voorkomt \ x x*x + 3*x + 2 de functie die die expressie uitrekent Lambda ? x . x*x + 3*x + 2 x . x*x + 3*x + 2 x . x*x + 3*x + 2 x . x*x + 3*x + 2 (LAMBDA x)( x*x + 3*x + 2 ) \ x x*x + 3*x + 2 \ x -> x*x + 3*x + 2 Toepassing: priemgetallen deelbaar :: Int Int Bool deelbaar t n = (t/n)*n == t delers :: Int [Int] delers x = filter (deelbaar x) [2..x-1] priem :: Int Bool priem x = null (delers x) priem = null . delers priemgetallen :: [Int] priemgetallen = filter priem [2..1000] Toepassing: dag van de week > dag 31 12 2002 “dinsdag” dag d m j = weekdag (nummer d m j) weekdag 0 = “zondag” weekdag 1 = “maandag” weekdag 2 = “dinsdag” etc. Toepassing: dag van de week nummer d m j = ( ( j-1) * 365 + ( j-1) / 4 - ( j-1) / 100 + ( j-1) / 400 + sum (take (m-1) (ms j)) +d ) `rem` 7 elk jaar 1 dag later, want 365 = 52*7+1 Toepassing: dag van de week ms j = [ 31, feb, 31, 30, 31, 30 , 31, 31, 30, 31, 30, 31 ] where feb | schrik j = 29 | True = 28 schrik j | deelb j 100 = deelb j 400 | True = deelb j 4 Toepassing: differentiëren diff :: (FloatFloat) (FloatFloat) diff :: (FloatFloat) Float Float diff f x = ( f (x+h) – f (x) ) / h where h = 0.000001 Toepassing: nulpunt nulpunt :: (FloatFloat) Float nulpunt f = until ok verbeter 1.0 where ok x = ... verbeter x = ... Methode van Newton verbeter b = b – f b / diff f b ok b = abs (f b) < 0.0001 fb b-d b d = f(b) / f’(b) Toepassing: inverse wortel a = nulpunt (\x x*x – a) arcsin a = nulpunt (\x sin x – a) log a = nulpunt (\x exp x – a) inverse :: (FloatFloat) (FloatFloat) inverse f a = nulpunt (\x f x – a) Hoger-ordefuncties op lijsten Doorloop een lijst en ... [a] [b] filter :: (aBool) [a] [a] map :: (ab) doe dit pak deze foldr :: (aaa) a [a] a combineer zo Currying Type f :: Int Bool String Aanroep > f 7 True “hoi” rechts-associatief links-associatief zonder haakjes!