Pattern Matching
Funktionen werden durch Muster definiert; die erste passende Zeile gewinnt:
beschreibe :: Int -> String
beschreibe 0 = "null"
beschreibe 1 = "eins"
beschreibe n
| n < 0 = "negativ"
| even n = "gerade"
| otherwise = "ungerade"
erstes :: [a] -> Maybe a
erstes [] = Nothing
erstes (x : _) = Just x
laenge :: [a] -> Int
laenge [] = 0
laenge (_ : rest) = 1 + laenge rest
summe :: [Int] -> Int
summe [] = 0
summe (x : xs) = x + summe xs
tuplePlus :: (Int, Int) -> Int
tuplePlus (a, b) = a + b
main :: IO ()
main = do
mapM_ (putStrLn . beschreibe) [0, 1, -5, 4, 7]
print (erstes [10, 20], erstes ([] :: [Int]))
print (laenge "Haskell", summe [1 .. 100], tuplePlus (3, 4))
let liste@(kopf : _) = [5, 6, 7] -- as-Muster: ganze Liste und Kopf
print (kopf, length liste)null eins negativ gerade ungerade (Just 10,Nothing) (7,5050,7) (5,3)
_ignoriert einen Wert(x : xs)zerlegt eine Liste in Kopf und Restname@musterbindet das Ganze und zerlegt es zugleich
Guards, if, case, let, where
bmi :: Double -> Double -> String
bmi gewicht groesse
| wert < 18.5 = "Untergewicht"
| wert < 25 = "Normalgewicht"
| wert < 30 = "Übergewicht"
| otherwise = "Adipositas"
where
wert = gewicht / groesse ^ 2
wochentag :: Int -> String
wochentag n = case n of
1 -> "Montag"
2 -> "Dienstag"
_ | n `elem` [6, 7] -> "Wochenende"
| otherwise -> "anderer Tag"
kreis :: Double -> (Double, Double)
kreis r = (flaeche, umfang)
where
flaeche = pi * r ^ 2
umfang = 2 * pi * r
abstand :: (Double, Double) -> (Double, Double) -> Double
abstand (x1, y1) (x2, y2) =
let dx = x2 - x1
dy = y2 - y1
in sqrt (dx * dx + dy * dy)
main :: IO ()
main = do
putStrLn (bmi 70 1.75)
print (map wochentag [1, 2, 6, 3])
print (kreis 1)
print (abstand (0, 0) (3, 4))
print (if 10 > 5 then "größer" else "kleiner")Normalgewicht ["Montag","Dienstag","Wochenende","anderer Tag"] (3.141592653589793,6.283185307179586) 5.0 "gr\246\223er"
where gehört zur Funktion und sieht deren Argumente, let ... in ... ist ein Ausdruck. otherwise ist einfach True.
Rekursion statt Schleifen
Da es keine veränderlichen Variablen gibt, wiederholt man mit Rekursion:
fib :: Int -> Integer
fib n = go n 0 1
where
go 0 a _ = a
go k a b = go (k - 1) b (a + b) -- Akkumulator: Endrekursion
ggT :: Int -> Int -> Int
ggT a 0 = a
ggT a b = ggT b (a `mod` b)
potenz :: Integer -> Int -> Integer
potenz _ 0 = 1
potenz b e
| even e = let h = potenz b (e `div` 2) in h * h
| otherwise = b * potenz b (e - 1)
collatz :: Int -> [Int]
collatz 1 = [1]
collatz n
| even n = n : collatz (n `div` 2)
| otherwise = n : collatz (3 * n + 1)
hanoi :: Int -> String -> String -> String -> [(String, String)]
hanoi 0 _ _ _ = []
hanoi n von nach hilfe = hanoi (n - 1) von hilfe nach ++ [(von, nach)] ++ hanoi (n - 1) hilfe nach von
main :: IO ()
main = do
print (map fib [0 .. 10])
print (fib 90)
print (ggT 48 18)
print (potenz 2 100)
print (collatz 6)
print (length (hanoi 10 "A" "C" "B"))
print (hanoi 2 "A" "C" "B")[0,1,1,2,3,5,8,13,21,34,55]
2880067194370816120
6
1267650600228229401496703205376
[6,3,10,5,16,8,4,2,1]
1023
[("A","B"),("A","C"),("B","C")]Lazy Evaluation
Haskell berechnet Werte erst, wenn sie gebraucht werden. Dadurch sind unendliche Listen möglich:
naturalZahlen :: [Integer]
naturalZahlen = [1 ..]
fibs :: [Integer]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
primzahlen :: [Int]
primzahlen = sieb [2 ..]
where sieb (p : xs) = p : sieb [x | x <- xs, x `mod` p /= 0]
main :: IO ()
main = do
print (take 5 naturalZahlen)
print (take 12 fibs)
print (takeWhile (< 40) primzahlen)
print (fst (1, undefined)) -- undefined wird nie ausgewertet
print (take 3 (cycle "ab"), take 3 (repeat 'x'), take 4 (iterate (* 2) 1))
print (head (filter ((> 1000) . (^ 2)) [1 ..]))[1,2,3,4,5]
[0,1,1,2,3,5,8,13,21,34,55,89]
[2,3,5,7,11,13,17,19,23,29,31,37]
1
("aba","xxx",[1,2,4,8])
32Merke
- Pattern Matching auf Werte, Tupel, Listen (
x : xs);_ignoriert - Guards (
| bedingung),where,let ... in,case ... of,if ... then ... else - Rekursion mit Akkumulatoren (Endrekursion) ersetzt Schleifen
- Lazy Evaluation erlaubt unendliche Datenstrukturen
Aufgabe
Schreibe anzahlVorkommen :: Eq a => a -> [a] -> Int rekursiv.