Haskell
Falco Nogatz
24. Juli 2012
Übungen zum
PDP-Repetitorium
Geben Sie für folgende Haskell-Ausdrücke jeweils an, ob sie korrekt sind, sowie ggf. einen zugehörigen Typen:
1.1
(1.1)
(1,1)
true
'string'
"c"
['1', '2', '3', '4']
::.
1.1 :: Float oder 1.1 :: Double (1.1) :: Float oder Double, ist genau das gleiche (1,1) :: (Int, Int) ist Tupel, da Komma! true nicht typkorrekt, da kleingeschrieben 'string' nicht typkorrekt, da einfache Hochkomma "c" :: String ['1', '2', '3', '4'] :: String oder ['1', '2', '3', '4'] :: [Char]
Geben Sie für folgende Haskell-Ausdrücke jeweils an, ob sie korrekt sind, sowie den allgemeinsten Typ:
1.1
(1.1) s.o.
(1,1)
true True
'string' 's'
"c"
['1', '2', '3', '4']
1.1 :: (Fractional a) => a
(1,1) :: (Num a, Num b) => (a, b) 2 Typvariablen, da z.B. Int+Float
True :: Bool
's' :: Char
"c" :: String
['1', '2', '3', '4'] :: String
Bestimmen Sie jeweils den allgemeinsten Typ der folgenden Haskell-Funktionen:
not
(<)
(>=)
(^)
not :: Bool -> Bool
(<) :: (Ord a) => a -> a -> Bool
(>=) :: (Ord a) => a -> a -> Bool Ord impliziert bereits Eq
(^) :: (Num a, Integral b) => a -> b -> a
Bestimmen Sie jeweils den allgemeinsten Typ der folgenden Haskell-Ausdrücke:
(+1)
(/0)
((^) 3)
(^3)
2^3
(+1) :: (Num a) => a -> a (/0) :: (Fractional a) => a -> a syntaktisch korrekt ((^) 3) :: (Integral a, Num b) => a -> b (^)::(Integral b, Num a) => a -> b -> a (^3) :: (Num a) => a -> a 2^3 :: (Num a) => a
Erzeugen Sie mittels Mengenkomprehension folgende Listen:
[n^4-2*n | n <- [2,4..]] [n | n <- [1..], n `mod` 11 == 3, n `mod` 13 == 7] [(n, (p, (n-p))) | n <- [1..], p <- [1..(n `div` 2)], not(isPrime n), isPrime p, isPrime (n-p)]
[1.0,1.3,1.7,2.0,2.3,2.7,...]
[z+d | z <- [1..], d <- [0,0.3,0.7]] [x+y+z | x <- [0,0.01,0.02,0.05,0.10,0.20,0.50,1.00,2.00], y <- [0,0.01,0.02,0.05,0.10,0.20,0.50,1.00,2.00], z <- [0.01,0.02,0.05,0.10,0.20,0.50,1.00,2.00], (x == 0 && y == 0) || (x < y && y < z)]
Klausuraufgabe SS11-2
Bestimmen Sie jeweils den Typ der folgenden Haskell-Ausdrücke:
('1', '2':"3", 4 < 5) [(last, tail), (head, take 5)] [(+), (-)] [map (const True), map not]
Klausuraufgabe SS11-2
Bestimmen Sie jeweils den Typ der folgenden Haskell-Ausdrücke:
('1', '2':"3", 4 < 5) :: (Char, String, Bool) [(last, tail), (head, take 5)] :: [ ([a] -> a, [b] -> [b]) ] [(+), (-)] :: Num a => [a -> a -> a] [map (const True), map not] :: [ [Bool] -> [Bool] ]
Definieren Sie folgende Funktionen. Verwenden Sie wenn nötig explizite Rekursion.
addPair (a,b) (c,d) = (a+c, b+d)
map f (x:xs) = f x : map f xs map _ [] = []
zip (x:xs) (y:ys) = (x,y) : zip xs ys zip _ _ = []
unzip ((x,y):ls) = (x:xs, y:ys) where (xs, ys) = unzip ls unzip [] = ([],[])
addPairs [] = (0,0) addPairs ((a,b):xs) = (a+c, b+d) where (c,d) = addPairs xs
zipWith f (x:xs) (y:ys) = (f x y) : zipWith f xs ys zipWith _ _ _ = []
Definieren Sie folgende Funktionen mit Hilfe von foldl oder foldr:
length = foldr (\x y -> 1+y) 0 length' = foldl (\x y -> x+1) 0
quadratsumme n = foldr (\x y -> x^2 + y) 0 [1..n] quadratsumme' n = foldl (\x y -> x + y^2) 0 [1..n]
reverse = foldr (\x y -> y++[x]) [] reverse' = foldl (\x y -> [y]++x) []
fak n = foldr (*) 1 [1..n]
Über einen rekursiven Datentyp soll die häusliche Verkabelung von Elektro-Geräten abgebildet werden. Ein Stecker führt entweder auf ein Geraet (Attribut Name) oder eine Steckdosenleiste (Attribut Plaetze).
/\ Steckdosenleiste 5 / \ / \ / \ Geraet "TV" /|\ Steckdosenleiste 3 / | \ / | \ / | \ / | \ / | \ Geraet "Hifi" | Geraet "Telefon" Geraet "Kühlschrank"
type Plaetze = Int data Stecker = Steckdosenleiste Plaetze [Stecker] | Geraet String steckerBeispiel = Steckdosenleiste 5 [Geraet "TV", Steckdosenleiste 3 [Geraet "Hifi", Geraet "Telefon", Geraet "Kühlschrank"] ]
Geben Sie eine Funktion ueberbelegt :: Stecker -> Bool an, die True zurückgibt, falls es eine Steckdosenleiste gibt, an die mehr Geräte oder Steckdosenleisten angeschlossen sind, als sie Plätze hat.
ueberbelegt :: Stecker -> Bool ueberbelegt stecker = not (foldStecker (\string -> True) (\plaetze leiste -> and leiste && plaetze >= length leiste) stecker)
Bei der Huffman-Codierung handelt es sich um ein einfaches Datenkompressionsverfahren. Dabei wird ausgenutzt, dass Zeichen in einem Text unterschiedlich oft vorkommen. So erhalten häufig auftretende Buchstaben kurze Codewörter und seltene Buchstaben längere. Um die optimale Codelänge zu erhalten, bilden die Buchstaben anhand ihrer Häufigkeit die Blätter eines binären Entscheidungsbaums.
Beispiel:
/\ / \ (0) / \ (1) / \ a /\ / \ (0) / \ (1) / \ /\ d / \ (0) / \ (1) / \ b c
So lässt sich 'b' durch den Code '100' darstellen, der häufigste Buchstabe 'a' wird durch '0' codiert.
Erstellen Sie einen Datentyp 'HuffmanTree' und geben Sie die Definition des oben
gezeigten Binärbaums an.
Hinweis: Gehen Sie davon aus, dass der linke Ast des Baums stets implizit durch
'0' codiert wird, der rechte durch '1'.
data HuffmanTree = Node HuffmanTree HuffmanTree | Bst Char deriving (Eq, Ord, Show) huffmanBeispiel :: HuffmanTree huffmanBeispiel = Node (Bst 'a') (Node (Node (Bst 'b') (Bst 'c')) (Bst 'd'))
Definieren Sie für diesen Datentypen rekursiv eine Funktion buchstaben :: HuffmanTree -> Int, die die Anzahl der im HuffmanTree hinterlegten Buchstaben zurückliefert.
buchstaben :: HuffmanTree -> Int buchstaben (Bst _) = 1 buchstaben (Node l r) = buchstaben l + buchstaben r -- buchstaben huffmanBeispiel == 4
Definieren Sie für diesen Datentypen eine fold-Funktion foldHuffman!
foldHuffman :: (Char -> a) -> (a -> a -> a) -> HuffmanTree -> a foldHuffman bf nf = m where m (Bst c) = bf c m (Node left right) = nf (m left) (m right)
Definieren Sie die o.g. buchstaben Funktion über foldHuffman!
buchstaben :: HuffmanTree -> Integer buchstaben = foldHuffman (\x -> 1) (+)
Definieren Sie über foldHuffman eine Funktion elemHuffman :: Char -> HuffmanTree -> Bool, die prüft, ob ein Zeichen im HuffmanTree gespeichert ist!
elemHuffman :: Char -> HuffmanTree -> Bool elemHuffman char = foldHuffman (\c -> char == c) (||)
... zum Repetitorium gibt's hier:
fnogatz.github.io/talks/pdp-rep-12/haskell/
Thanks to Benjamin Erb for the html5slides and uulm template.
Title image: Miran Lipovača under CC BY-NC-SA 3.0