Haskell - KU Leuven

Download Report

Transcript Haskell - KU Leuven

Haskell
Functioneel programmeren
(S)DT 2012-2013
1
Bijkomend materiaal




de Haskell website http://www.haskell.org/.
Op de "Learning Haskell" pagina
http://www.haskell.org/haskellwiki/Learning_Haskell
vind je veel bijkomende informatie.
Je vindt er online materiaal, bijvoorbeeld
Learn You a Haskell for Great Good (tutorial)
http://learnyouahaskell.com/
Yet Another Haskell Tutorial
http://www.cs.utah.edu/~hal/docs/daume02yaht.pdf
of een nederlandstalige cursustekst
(http://people.cs.uu.nl/jeroen/courses/fp-nl.pdf).
(S)DT 2012-2013
2
Bijkomend materiaal



In de didactische cluster van de CBA vind je
Programming in Haskell
Graham Hutton, University of Nottingham
Cambridge University Press, January 2007
(http://www.cs.nott.ac.uk/~gmh/book.html).
Ook video lectures gebaseerd op het boek!!
!!!!! Er is een online manual die je ook tijdens
het examen lokaal kan raadplegen: not
(http://zvon.org/comp/r/ref-Haskell.html)
(S)DT 2012-2013
3
Bijkomend materiaal



!!!!! Er is een online manual die je ook tijdens
het examen lokaal kan raadplegen: not
(http://zvon.org/comp/r/ref-Haskell.html)
Maar,
http://zvon.org/other/haskell/Outputglobal
(Gequoteerde) oefeningen +
modeloplossingen
(S)DT 2012-2013
4
Haskell
Deel 1
Introductie; lijsten in Haskell;
lui uitvoeringsmechanisme;
polymorfe functies
(S)DT 2012-2013
5
Een eenvoudig Haskell programma
fib :: Int -> Int
-- een typedeclaratie voor fib
fib 0 = 1
fib 1 = 1
fib n = (fib (n-1)) + (fib (n-2))
fib is een recursieve functie die kan toegepast worden op 1 argument
dat een integer moet zijn en dan als waarde een integer teruggeeft.
zet definitie in een bestand, bijvoorbeeld f.hs
laad in in ghci (Haskell platform http://hackage.haskell.org/platform/)
doe functie-oproepen
(S)DT 2012-2013
6
# GHCi, version 6.12.3: http://www.haskell.org/ghc/
:? for help
...
-- commentaar tot einde lijn
Prelude> :load f
Main> fib 3
3
Main> fib 6
13
Main> fib (-1)
………………………………
-- :load is directief
-- pas fib toe op 3
-- resultaat is 3
computatie gebeurt door ....
Functionele taal ….
Bouwstenen in je programma’s:
herbruikbare functies (die modelleren algoritmen)
Expressies in een functionele taal : waarde gebaseerd
(S)DT 2012-2013
7
Main> :type fib
fib :: Int -> Int
Main> :type (+)
(+) :: Num a => a -> a -> a
“Voor alle types a die de Num operaties ondersteunen”, (+) is een
functie die twee argumenten van het type a afbeeldt op een
resultaat van het type a.
Int is een voorbeeld van een type dat de Num operaties ondersteunt:
de funties (+), (-), (*), ...
(S)DT 2012-2013
8
-- variabele a
Main> fib a
<interactive>:1:4: Not in scope: `a‘
Main> fib "asd“
-- de string "asd“ is in feite een lijst van Char
-- [Char]
-- type fout: [Char] is geen Int
<interactive>:1:0:
Couldn't match expected type `Int' against inferred
type `[Char]'
In the first argument of `fib', namely `"asd"'
In the expression: fib "asd"
In the definition of `it': it = fib "asd"
(S)DT 2012-2013
9
Haskell: merk op








Haskell is getypeerd (statisch en sterk)
een functie wordt gedefinieerd aan de hand van
verschillende clauses
(pattern) matching gebeurt van boven naar onder en
eerste argumenten-match wordt genomen
er zijn “ingebouwde” functies (+ - )
veranderlijken en functienamen beginnen met kleine
letter
type begint met een hoofdletter (enkel al Int)
functies met letter in prefix (kan anders)
speciale tekens in infix
(S)DT 2012-2013
10
Syntactisch alternatieve definitie van fib
fib n = if n == 0 then 1
-- else verplicht
else if n == 1 then 1
else (fib (n-1)) + (fib (n-2))
Maar
fib n = if n == 0 then 1 else
if n == 1 then 1
else (fib (n-1)) + (fib (n-2))
Prelude>:l f.hs
[1 of 1] Compiling Main
( fib.hs, interpreted )
f.hs:14:0: parse error (possibly incorrect indentation)
Failed, modules loaded: none.
(S)DT 2012-2013
11
Andere versies van fib
fib :: Int -> Int
fib n = fib2 n 1 0
fib2 :: Int -> Int -> Int -> Int
fib2 0 n _ = n
fib2 i n m = fib2 (i-1) (m+n) n
vroeger
Main> fib 100
-1869596475
nu
Main> fib 100
1298777728820984005
(S)DT 2012-2013
12
Interactieve evaluatie (:set +t)
Main> 8 + 2
10
it :: Integer
Main> it + 3
13
it :: Integer
Main> let x = 3+4
x :: Integer
Main> x
7
it :: Integer
Main> :show bindings
x :: Integer = 7
it :: Integer = 7
(S)DT 2012-2013
13
Haskell: merk verder op


waar zijn de typedeclaraties bij sommige vb?
het type van een functie die meerdere argumenten
kan hebben wordt genoteerd door
A1 -> A2 -> A3 -> R
(S)DT 2012-2013
14
Type-declaraties, -inferentie en -checking
f a b = g a (h b)
-- haakjes zijn nodig
g :: R -> S -> T
…
-- definitie van g
h :: Q -> P
…
-- definitie van h
1. het type van f moet dan zijn:
f :: R -> Q -> T
2. is het type van g en h consistent?
enkel indien P == S
-- beetje te straf
Haskell kan types infereren (1) en nakijken (2)
gebaseerd op Hindley-Milner type systeem (van ML)
(S)DT 2012-2013
15
Currying en waarom de haakjes?


eigenlijk heeft een functie altijd maar 1 argument en
is dus een “curried” functie
voor een functie f :: A -> B -> C hebben we dat
(f a)


::
B -> C
dus, een functie met n argumenten, toegepast op 1
argument geeft als resultaat een functie met n-1
argumenten
bovenstaande declaratie is equivalent met
f :: A -> (B -> C)


en totaal verschillend van f :: (A -> B) -> C
tenslotte, g a h b == (((g a) h) b) en niet g
(S)DT 2012-2013
a (h b)
16
Curried versie van de optelling
-- versie met tuple als argument
add :: (Int,Int) -> Int
add (x,y) = x + y
-- curried versie cadd
cadd :: Int -> Int -> Int
cadd x y = x + y
-- hetzelfde resultaat maar voor cadd wordt er eerst
(cadd x) berekend en dan …
-- -> is rechts-associatief dus geen haakjes nodig in
cadd :: Int -> (Int -> Int)
-- functie-oproepen zijn links-associatief dus geen
haakjes nodig in
cadd 3 4
want is in feite ((cadd 3) 4)
--
(S)DT 2012-2013
17
Curried functies


Meer flexibel dan functies met tuples
Partieel toegepaste functies kunnen erg nuttig zijn
plus4
= (cadd 4)
-- enkele nuttige functies gedefinieerd door sections
isNul = (== 0)
verdubbel = (2*)
tweeTotde = (2^)

Een infix operator is in feite ook een curried functie
(+) 1 2
(S)DT 2012-2013
18
Operator section
partieel toegepaste operator: (+
3)
en (3
+)
(op a) b = b op a
(a op) b = a op b
Main>:t (-3)
(-3) :: (Num a) => a
(S)DT 2012-2013
19
Currying, genoemd naar Haskell Curry 19001982


Logicus die rond functie theorie werkte
een simpel theoretisch model:
enkel functies met 1 argument, bv. lambda calculus
f :: (Int -> Int) -> Int -> Int
f g a = g a
-- apply g to a
Main> f (+3) 4
7
Main> f (3-) 4
-1
Main> f (*4) 4
16
Wat is (f (3+))?
 Alternatieve def voor f?
(3+) $ 4

(S)DT 2012-2013
20
Verschil
f :: ( Int -> Int -> Int) -> Int -> Int -> Int
f g a b = g a b
Main> f (+) 3 4
7
Main> f (-) 3 4
-1
Wat is (f (+))?
Wat is f?
(S)DT 2012-2013
21
Hogere orde functies






functies kunnen als argument een functie hebben
functies kunnen als resultaat een functie teruggeven
functies kunnen als parameter van andere functies
worden gebruikt -- later
toepassen van een functie f op 1 argument a
noteren we door (f a)
eventueel zonder haakjes
vergelijk met Lisp (f a b)!!!
(S)DT 2012-2013
22
Geschiedenis




1920-1930: functies als berekeningsmodel, M.
Schönfinkel, Haskell Curry en Alonzo Church
(lambda calculus)
1950: eerste functionele programmeertaal,
Lisp van John McCarthy (emacs)
1978: Backus (Fortran;Backus Naur Form) in
zijn Turing Award Lecture: “Can programming
be liberated from the Von Neumann style”
pleidooi voor echt functioneel programmeren
1980: getypeerde functionele talen
programmeertalen: ML, Scheme (een
aanpassing van Lisp), Miranda, Gofer, Clean
(S)DT 2012-2013
23
Geschiedenis



1987: groep onderzoekers definieren de taal Haskell
Richard Bird, Paul Hudak, John Hughes, Neil Jones,
Simon Peyton Jones, Philip Wadler, ....
“referential” transparantie
“substitute equals for equals”
http://www.defmacro.org/ramblings/fp.html
(S)DT 2012-2013
24
(S)DT 2012-2013
25
Prelude



The Prelude: a standard module imported by
default into all Haskell modules.
For more documentation, see the Haskell 98
Report http://www.haskell.org/onlinereport/.
GHC Documentation (Basic) Libraries
Prelude, Data.List specificaties + source
(S)DT 2012-2013
26
!!!!http://zvon.org/comp/r/refHaskell.html (en ook oude versie)

The Haskell reference is based on Haskell 98
Report and Haskell 98 Libraries Report
and a substantial part of descriptions comes
from these specifications.
(S)DT 2012-2013
27
Let expressies
fib n = if n == 0
else if n
else let
a =
b =
in a
then 0
== 1 then 1
fib (n-1)
fib (n-2)
+ b
a en b zijn lokale variabelen binnen de laatste else tak
de = is geen toekenning!!! Maar …
let y
= a*b
f x = (x+y)/y
in f c + f d
(S)DT 2012-2013
28
Where clauses
fib :: Int -> Int
fib n = fib2 n 1 0
where fib2 0 n _ = n
fib2 i n m = fib2 (i-1) (m+n) n
fib2 is lokaal aan fib (clause die er juist voor staat)
fib2 is elders niet zichtbaar
fib2 heeft geen type declaratie
genest gebruik van syntax mogelijk
(S)DT 2012-2013
29
To do





start ergens ghci op
type wat kleine programma’s in
laad en voer de oproepen uit
maak fouten tegen types, indentatie en syntax
definieer max :: Int -> Int -> Int
max a b



en ook maxdrie a b c
schrijf minstens 1 nieuwe hogere orde functie
ontdek een probleem met fib (2^100)
(S)DT 2012-2013
30
LIJSTEN IN HASKELL
(S)DT 2012-2013
31
Lijsten in Haskell




een lijst is een rij zonder constante tijd
random toegang en
gegeven een lijst kan er in constante tijd een
element aan toegevoegd worden (van voor).
(anders is het een array)
een lijst is leeg of een element gevolgd door
een lijst
een lijst heeft elementen die alle hetzelfde
type hebben.
(S)DT 2012-2013
32
Een lijst van Int



een lege lijst []
lijst met elementen 4 5 1
[4,5,1]
alternatieve notaties voor [4,5,1]
4 : [5,1]
4 : 5 : 1 : []
Prelude> :t (:)
(:) :: a -> [a] -> [a]

Hoe in Prolog??
(S)DT 2012-2013
33
Lijsten aan elkaar hangen
append :: [Int] -> [Int] -> [Int]
append []
l = l
append (x:xs) a = x : (append xs a)
Is er een verschil met het concateren van lijsten in
Prolog of linked lists in Java?
In Prelude
[]
++ ys
= ys
(x:xs) ++ ys
Let op: append
x:xs
= x : (xs ++ ys)
wordt opgevat als
(append x) : xs
(S)DT 2012-2013
34
Herschrijven als uitvoeringsmodel
[]
++ ys
(x:xs) ++ ys
=
=
=
=
= ys
= x : (xs ++ ys)
[1,2] ++ [4,5]
(1:2:[]) ++ (4:5:[])
1 : ((2:[]) ++ (4:5:[]))
1 : 2 : ([] ++ (4:5:[]))
1 : 2 : 4 : 5 : []
(S)DT 2012-2013
35
Let op: vergelijk
[2] ++ [3,4,5]
2 ++ [3,4,5]
<interactive>:1:0:
No instance for (Num [a])
arising from the literal `2' at <interactive>:1:0
Possible fix:add an instance declaration for (Num [a])
In the first argument of `(++)', namely `2'
In the expression: 2 ++ [3, 4, 6]
In the definition of `it': it = 2 ++ [3, 4, 6]
(S)DT 2012-2013
36
Let op: vergelijk
2 : [3,4,5]
[2] : [3,4,5]
No instance for (Num [t])
arising from the literal `5' at <interactive>:1:11
Possible fix:add an instance declaration for (Num [t])
In the expression: 5
In the second argument of `(:)', namely `[3, 4, 5]'
In the expression: [2] : [3, 4, 5]
(S)DT 2012-2013
37
Lengte van een lijst
listlength :: [Int] -> Int
listlength []
= 0
listlength (x:xs) = 1 + (listlength xs)
of
listlength l = ll l 0
where ll []
acc = acc
ll (x:xs) acc = ll xs (acc+1)
Is er een reden om de ene beter te vinden dan
de andere?
(S)DT 2012-2013
38
Insertion sort
isort :: [Int] -> [Int]
isort []
=
isort (x:xs) =
where insert
insert
[]
insert x (isort xs)
x []
= [x]
x (y:ys) = if x < y
then (x: y : ys)
else (y: (insert x ys))
(S)DT 2012-2013
39
To do



schrijf een functie die van een lijst van Ints
enkel de positieve getallen behoudt
schrijf een functie die de som teruggeeft van
de positieve getallen in een lijst van Ints.
schrijf een functie die het maximum van een
lijst van Ints teruggeeft
(S)DT 2012-2013
40
LUI
UITVOERINGSMECHANSIME
(S)DT 2012-2013
41
Parameter passing mechanisme

Wat ken je al?

Java: call by value





actueel argument wordt geëvalueerd voor de methode
wordt opgeroepen
??
Haskell: actueel argument wordt geëvalueerd
wanneer de waarde ervan nodig is
Haskell is lui
Haskell heeft call by need
(S)DT 2012-2013
42
Wat betekent lui?
g a b = h (a+b)
h i = 9
> g 3 4
Waarom ooit de (3+4) uitrekenen als geen
enkele functie die waarde ooit zal gebruiken?
(S)DT 2012-2013
43
De essentie van luiheid



Een expressie wordt maar gereduceerd tot
een waarde indien de waarde nodig is.
Een expressie wordt slechts één keer
gereduceerd tot een waarde
kwadraat i = i * i
telop x y = x + y
kwadraat (telop 6 2)
contrasteer met call by value, call by name
(S)DT 2012-2013
44
Voorbeeld && : luie evaluatie van
argumenten
(&&),
False
True
False
True
(||)
&& x
&& x
|| x
|| x
::
=
=
=
=
Bool -> Bool -> Bool
False
x
x
True
Prelude> 4 < 5 && 3 < (5/0)
Program error????
Ghci: True -- 3 < Infinitity !!
Prelude> 5 < 4
False
&&
3 < (5/0)
(S)DT 2012-2013
45
Voorbeeld: luie matching
f
f
f
f
:: [Int] -> [Int]
[]
y = 0
(a:x) [] = 0
(a:x) (b:y) = a +
-> Int
add1 []
= []
add1 (x:xs) = (x+1): add1 xs
b
f
=
=
=
=
=
(add1 [4,5,6]) (add1 [10,20,30])
f ((4+1):add1 [5,6]) (add1 [10,20,30])
f (5:add1 [5,6]) (add1 [10,20,30])
f (5:add1 [5,6]) (11: add1 [20,30])
5 + 11
16
(S)DT 2012-2013
46
Wat met accumulator versie van
listlength??
listlength l = ll l 0
where ll []
acc = acc
ll (x:xs) acc = ll xs (acc+1)
Wat gebeurt er met (acc+1)???
De hele som wordt opgebouwd voor ze wordt berekend!!
where llstrict [] l = l
llstrict (x:xs) l = llstrict xs $! (l+1)
-- f $! x behaves as f x, except that the
evaluation of the argument x is forced before f is
applied
(S)DT 2012-2013
47
Luiheid en oneindige lijsten
plus1 :: [Int] -> [Int]
plus1 []
= []
plus1 (x: xs) = (x+1) : (plus1 xs)
langelijst :: [Int]
langelijst = (1 : (plus1 langelijst))




-- (*)
langelijst is een functie zonder argumenten, enkel resultaat
langelijst is een waarde die voldoet aan de vergelijking (*)
met call by value is (*) een onmogelijke definitie
zolang we maar eindig veel delen van langelijst nodig hebben is er
geen probleem: Haskell zal er niet meer berekenen
(S)DT 2012-2013
48
Hoe eindig veel elementen van een
oneindige lijst gebruiken?
take :: Int -> [Int] -> [Int]
take 0 _
= []
take n (x:xs) = x : take (n-1) xs
fib :: [Int]
fib = (1:1: (f 1 1 ))
where f a b = (a+b): (f b (a+b))
Main> take 3 [1,2,3,4,5]
[1,2,3]
Main> take 10 fib
[1,1,2,3,5,8,13,21,34,55]
Wat is de waarde van fib?
Welke functie zorgt voor welke evaluatie?
(S)DT 2012-2013
49
Kijk zelf na
Main> take 3 langelijst
[1,2,3]
Welke functie zorgt voor de evaluatie van welke
uitdrukking???
(S)DT 2012-2013
50
Extra voorbeeld
isSorted
isSorted
isSorted
isSorted
:: [Int]
[]
[_]
(x:y:ys)
-> Bool
= True
= True
= (x <= y) && isSorted
(y:ys)
iterate :: (a -> a) -> a -> [a]
iterate next x = x : iterate next (next x)
Main> isSorted (iterate (`div` 2) 8)
Main> isSorted (iterate (`div` 2) (-100))
Main> iterate (`div` 2) (factorial 100)
(S)DT 2012-2013
51
POLYMORFE FUNCTIES
(S)DT 2012-2013
52
Een voorbeeld
listlength:: [Int] -> Int
listlength [] = 0
listlength (_:xs) = 1 + listlength xs



Wat is er aan de clauses van listlength dat
maakt dat het alleen zou werken voor [Int] ?
Kan het ook werken met elementen van een
ander type? een willekeurig type?
Niet met die typedeclaratie natuurlijk!!
(S)DT 2012-2013
53
Nu als polymorfe functie
listlength:: [t] -> Int
listlength [] = 0
listlength (_:xs) = 1 + listlength xs



is een type-veranderlijke !!
lees bv. als: voor elk type t is listlength een
functie die toegepast op een lijst met type t
elementen een Int berekent
belangrijk: alle elementen van de lijst moeten
van hetzelfde type zijn!!!
t
(S)DT 2012-2013
54
Bekende functies: polymorfe versie
append :: [t] -> [t] -> [t]
append []
l = l
append (x:xs) a = x : append xs a
-- waarom niet [a] -> [b] -> [c] ???
take :: Int -> [t] -> [t]
take 0 _
= []
take n (x:xs) = x : take (n-1) xs
(S)DT 2012-2013
55
Nieuwe polymorfe functies
id :: a -> a
id x = x
-- identiteits-functie
map :: (a -> b) -> [a] -> [b]
map f []
= []
map f (h: r) = (f h) : map f r
Main> map (+1) [1,2,3]
[2,3,4]
g i = if i > 0 then True else False
> map g [-1,3,-4,4]

meer dan 1 type parameter!!! soms a == b
(S)DT 2012-2013
56
Tuples
lijsten versmelten en een nieuw data type
zip :: [a] -> [b] -> [(a,b)]
zip [] _
= []
zip _
[]
= []
zip (x:xs) (y:ys) = ( (x,y) : (zip xs ys))
Main> zip [1,2,3,4] [True,False,True]
[ (1,True), (2,False), (3,True)]
tuples van elke grootte zijn ingebouwd en
pattern matchen enkel met tuples van gelijke
grootte
(S)DT 2012-2013
57
Guards als syntactische suiker
merge
merge
merge
merge
:: [Int] -> [Int]
[] l = l
l [] = l
(x:xs) (y:ys) =
if (x < y) then (x
else if x > y then
else (x : merge xs
-> [Int]
: merge xs (y:ys))
(y : merge (x:xs) ys)
ys)
-- of ook : laatste clause met guards
merge (x:xs) (y:ys) | x < y = (x : merge xs (y:ys))
| x > y = (y : merge (x:xs) ys)
| True = (x : merge xs ys)
(S)DT 2012-2013
58
Verschillende stijlen in Haskell:
declaratie <-> expressie

een functie-definitie is een opeenvolging van
onafhankelijke gelijkheden
sign x | x>0 = 1
| x==0
= 0
| x<0 = -1

een functie-definitie is een expressie
sign x = if x>0 then 1
else if x==0 then 0
else -1
(S)DT 2012-2013
59
Schrijf nu zelf





een functie quicksort voor [Int]
een functie die een oneindige lijst van alle
positieve oneven getallen specifieert
een functie die een oneindige lijst van alle
priemgetallen specifieert
een functie die nagaat of een gegeven getal
een priemgetal is
probeer een polymorfe sort te schrijven
(S)DT 2012-2013
60
Nog eens: luie evaluatie






Actueel argument van een functie: uitgestelde
berekening
Werkt met een closure: te evalueren expressie +
relevante bindingen
Closures nemen plaats in op de heap
(ook ints, lists, …)
Call by need en call by value: zelfde antwoord als
het programma eindigt
MAAR nooit meer reductie-stappen want ..
Soms toch waarde berekenen: wanneer?
(S)DT 2012-2013
61
Stricte functies



Argument van een functie: als de waarde
ervan altijd nodig is, dan is de functie strict in
dat argument.
Voorbeeld: fact n , kwadraad i , telop x y
Maar project x y = x
constPi


x = 3.14
Voor stricte argumenten: compiler kan
beslissen toch uit te rekenen
Voor niet-stricte argumenten: (keten van)
closures nemen plaats op heap
(S)DT 2012-2013
62
Nut van oneindige lijsten? lui?




Programma: abstracter, eenvoudiger
Producer + consumer toepassingen met
corouting
Een tijdelijke lijst wordt “on demand”
opgebouwd
Enkel berekenen wat nodig is voor het vinden
van een oplossing
(S)DT 2012-2013
63
Wat met andere functionele talen??




Stricte talen (call by value): Lisp, Scheme,
ML, Erlang (concurrent)
Niet-stricte/luie talen (call by need): Miranda
(inspiratie voor Haskell), Hope, Clean
(concurrent)
Wat is het beste??
Implicaties van luiheid?
Puur functioneel!!
(S)DT 2012-2013
64
De lambda notatie



Een functie hoeft geen naam te hebben
Enkel een voorschrift om de functie te evalueren
Mogelijk in Haskell met de λ-notatie voor functies
plus1list = map plus1
where plus1 i = i + 1
-- ofwel ook
plus1list = map (\x -> x+1)

Meer algemeen
(\a b c d -> (fib a) + (head b) * c +d )

Wat is
(\x y -> x * y) 3
?
(S)DT 2012-2013
65
filter :: (t -> Bool) -> [t] -> [t]
filter p [] = []
filter p (x:xs)
| p x = x : rest
| otherwise = rest
where
rest = filter p xs
Miranda <-> Lisp, ML, Scheme
filter = \p -> \xs ->
case xs of
[] -> []
(x:xs) -> let
rest = filter p xs
in if (p x)
then x : rest
else rest
(S)DT 2012-2013
66
Lijsten van gehele getallen

Alsof Haskell vooraf definieerde:
[n..m] = if n > m then []
else n : [ (n+1) .. m]
[i ..] = (i : [(i+1) .. ])
dus
Main> [3..8]
[3,4,5,6,7,8]
Main> [-5..1]
[-5,-4,-3,-2,-1,0,1]
Main> take 4 [21..]
[21,22,23,24]
(S)DT 2012-2013
67
Functie samenstelling
filterpos::[Int] -> [Int]
filterpos [] = []
filterpos (x:xs)
| x > 0 = x : filterpos xs
| otherwise = filterpos xs
suml :: [Int] -> Int
suml [] = 0
suml (x:xs) = x + suml xs
addpos l = suml (filterpos l)
addpos2 = suml . filterpos
-- suml na filterpos
addpos3 = suml . (filter (>0))
addpos4 = foldr (+) 0 . filter (>0)
(S)DT 2012-2013
68
Functie samenstelling
Prelude> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
(f.g) x = f ( g x)
foldr :: (a->b->b) -> b -> [a] -> b
it takes the second argument and the last item of the list and applies
the function, then it takes the penultimate item from the end and the
result, and so on. See scanr for intermediate results.
Input: foldr (+) 5 [1,2,3,4]
Output: 15
-- (1 + ( 2 + (3 + (4 +5))))
Input: scanr (+) 5 [1,2,3,4]
Output: [15,14,12,9,5]
(S)DT 2012-2013
69