Gruppen 2 und 4
Samuel Teuber
propa@teuber.dev
https://teuber.dev/propa
Haskell ist anders, aber lasst euch davon nicht verwirren!
Mergesort: Nutzt die Algorithmen, die angegeben sind!
Zwei Optimierungsmöglichkeiten:
f (x:xs) True = [x]
f l False = l
...oder...
f l@(x:xs) a
| a = [x]
| otherwise = l
f l@(x:xs) a
| a = [x]
| otherwise = l
f [1,2,3] True
f [1,2,3] False
f x
| even x = x `div` 2
| odd x = (x-1) `div` 2
f' x = x `div` 2
f 5
f' 5
type Polynom = [Double]
cmult :: Polynom -> Double -> Polynom
cmult p c = map (*c) p
eval :: Polynom -> Double -> Double
eval p x = foldr (\a v -> a + v*x) 0 p
deriv :: Polynom -> Polynom
deriv [] = []
deriv p =zipWith (*) [1..] (tail p)
a0
collatz :: Int -> [Int]
collatz m = iterate next m
where
next :: Int -> Int
next an
| an `mod` 2 == 0 = an `div` 2
| otherwise = 3 * an + 1
num m = length (takeWhile (/= 1) (collatz m)))
num
in IntervalmaxNum a b = foldl maxPair (0,0) (map (\m -> (m, num m)) [a..b])
where maxPair (m,n) (m',n') = if n > n' then (m,n) else (m',n')
Klausuraufgabe
merge [] b = b
merge a [] = a
merge l1@(x:xs) l2@(y:ys)
| (x<y) = x:merge xs l2
| otherwise = y:merge l1 ys
primepowers n = foldr merge [] [map (^i) primes | i <- [1..n]]
Umfrage
Typ [I]: (a -> a) -> (a -> a)
Typ [II]: a -> a
Wenn eine Funktion Typ [II] hat, "dann hat sie eigentlich auch Typ [I]"
Wenn eine Funktion Typ [II] hat, dann kann man sie verwenden als hätte sie Typ [I]
...schon wieder...
...schon wieder...
Beispiel: Listen-Typ
[t]
ist der Typ von Listen mit Elementen vom Typ t
t
beliebigSichtweisen:
[ ]
erzeugen neue Typen aus bestehendenVergleichbares in Java: Generics
LinkedList<T>
... sind polymorph, denn...
s -> t
... beschreibt den Typ aller Funktionen von s
nach t
(s
,t
beliebig)
...sind polymorph, denn...
(,) :: s -> t -> (s,t)
...und umgekehrt...
fst :: (s,t) -> s
snd :: (s,t) -> t
...kennen wir auch schon...
foldr :: (a -> b -> b) -> b -> [a] -> b
type Name = (String, String)
type MNumber = Integer -- Für die Addition von Matrikelnummern...
type Address = (String, Integer, String) -- Straße, PLZ und Ort
type Grades = [(String, Double)] -- Fach Name und Note
type Student = (Name,MNumber, Address, Grades)
Ist das eine gute Idee?
Definition neuer Typen durch Auflistung aller Konstruktoren:
data Address = Address String Integer String
data UniversityPerson = Student String Integer Address
| Professor String Address
Ergibt die folgenden Konstruktoren:
Address :: String -> Integer -> String -> Address
Student :: String -> Integer -> Adress -> UniversityPerson
Professor :: String -> Adress -> UniversityPerson
Jede*r Student
und jede*r Professor
ist eine UniversityPerson
data UniversityPerson = Student String Integer
| Professor String
getName :: UniversityPerson -> String
getName (Student name _) = name
getName (Professor name) = name
getName (Student "Samuel" 424242)
getName (Professor "Prof. Dr. Snelting")
z.B. Realisierung von optionalen Werten:
data Maybe t = Nothing | Just t
Just True :: Maybe Bool
data Either t s = Option1 t | Option2 s
-- Übungsaufgabe 1 (2min)
process :: (t -> a) -> (s -> a) -> Either t s -> a
process f _ (Option1 a) = f a
process _ g (Option2 b) = g b
printBool :: Bool -> String
printBool False = "Aww, it's false"
printBool True = "Yay, it's true"
printInt :: Int -> String
printInt x
| x<=0 = "Nope, not gonna spread this negativity"
| (x>0) && (x<100) = "This number is pretty small"
| otherwise = "Woah that's a big number"
print' = process printBool printInt
:t print'
print' (Option1 False)
print' (Option2 (-101))
data Tree t = Leaf t | Node (Tree t) t (Tree t)
-- Übungsaufgabe 2:
-- Definiere einen polymorphen Datentyp für einfach verkettete Listen
-- Definiere eine Operation zur Berechnung der Listenlänge
data List a = End | Part a (List a)
listLength :: List a -> Int
listLength End = 0
listLength (Part a l) = 1 + (listLength l)
listLength (Part 2 End)
...endlich...
Eq
:class Eq t where
(==) :: t -> t -> Bool
(/=) :: t -> t -> Bool
x /= y = not (x == y)
x == y = not (x /= y)
instance Eq Bool where
True == True = True
False == False = True
x == y = False
Auch für Polymorphe Typen:
data Maybe t = Nothing | Just t
class Defaultable t where
getDefault :: t a -> a -> a
instance Defaultable Maybe where
getDefault (Just x) c = x
getDefault Nothing c = c
getDefault Nothing 1
getDefault (Just 10) 1
:t foldr
...für algebraische Datenstrukturen
Basierend auf innenliegenden Typen:
data Shape = Circle Double | Rectancle Double Double deriving Eq
Befindet sich ein Element in einem Baum?
-- Übungsaufgabe 3
data Tree t = Leaf t | Node (Tree t) t (Tree t)
treeFind :: (Eq a) => Tree a -> a -> Bool
treeFind (Leaf x) y = x == y
treeFind (Node x y z) a = treeFind x a || y==a || treeFind z a
myTree = Node (Node (Leaf "test") "foo" (Leaf "tset")) "abc" (Node (Leaf "42") "bar" (Leaf "24") )
treeFind myTree "test"
treeFind myTree "thisisnotinmytree"
map
aber für Bäume
-- Übungsaufgabe 4
data Tree t = Leaf t | Node (Tree t) t (Tree t) deriving Show
treeMap :: (a->b) -> Tree a -> Tree b
treeMap f (Leaf x) = Leaf (f x)
treeMap f (Node l x r) = Node (treeMap f l) (f x) (treeMap f r)
myTree = Node (Node (Leaf "test") "foo" (Leaf "tset")) "abc" (Node (Leaf "42") "bar" (Leaf "24") )
treeMap tail myTree
Typklasse für Datenstrukturen die Mappable
sind.
Wir wollen:
dMap
auf algebraischen Datentypen mit einem Parameter erlaubt class Mappable -- ...
Tree
instance Mappable Tree -- ...
-- Übungsaufgabe 5
class Mappable t where
dMap :: (a->b) -> t a -> t b
instance Mappable Tree where
dMap f t = treeMap f t