hoofdstuk 2

advertisement
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
FTF
F
F
associatief
FTF
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 :: (ab)  [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 :: (aBool)  [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 :: (aaa) 
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 :: (aBool) 
[a]  [a]
map :: (ab)
doe dit
pak deze
foldr :: (aaa)  a  [a]  a
combineer zo
Andere hogere-ordefuncties
until :: (aBool)  (aa)  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
(.) ::
(bc)  (ab) 
(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 :: (FloatFloat)  (FloatFloat)
diff :: (FloatFloat)  Float  Float
diff f x = ( f (x+h) – f (x) ) / h
where h = 0.000001
Toepassing: nulpunt
nulpunt :: (FloatFloat)  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 :: (FloatFloat)  (FloatFloat)
inverse f a = nulpunt (\x f x – a)
Hoger-ordefuncties op lijsten
Doorloop een lijst en ...

[a]  [b]
filter :: (aBool) 
[a]  [a]
map :: (ab)
doe dit
pak deze
foldr :: (aaa)  a  [a]  a
combineer zo
Currying
 Type
f :: Int  Bool  String
 Aanroep
> f 7 True
“hoi”
rechts-associatief
links-associatief

zonder
haakjes!
Download