-- Mischa Dieterle, FB 12 -- Philipps-Universität Marburg -- Einzeiliger Kommentar {- Mehrzeiliger Kommentar -} module HsExamples --Modulnamen: (ohne Namen wird Main angenommen und eine Funktion main erwartet) where -- imports import Prelude hiding (filter,map,foldr1) --Einfache Variablen x :: Int x = 3 --Einfache Funktionen square :: Int -> Int square x = x * x --ohne Typangabe: in ghci ":t square'" eingeben square' x = x * x --Einfache zweistellige Funktionen plus :: Int -> Int -> Int plus a b = a + b --Partielle Applikation / currying suc :: Int -> Int suc = plus 1 --Funktionskomposition (bei Funktionen mit einem Argument) sucsuc :: Int -> Int sucsuc = suc . suc -- or mit if then else oR,oR',oR'' :: Bool -> Bool -> Bool -- normalerweise Operator || oR x y = if x then True else y -- or mit Guards (hinter Guards müssen boolesche Ausdrücke stehen) oR' x y | x = True | (y == True) = True | otherwise = False -- or mit Pattern Matching oR'' True _ = True -- Argument True wird abgeglichen, Argument _ wird ignoriert oR'' False b = b -- Argumentvariable b wird gebunden --Polymorphie first :: a -> b -> a first x y = x r = (+) 3 4 --Listen leereListe = [] einerListe :: [Int] einerListe = 1 : [] -- Infixoperator : konstruiert aus Element und Liste zweierListe = 2 : einerListe zweierListe' = 2 : (1: []) zweierListe'' = 2 : 1 : [] -- Infixoperator : ist rechtsassoziativ dreierListe = 3 : zweierListe dreierListe' = 3 : (2: (1: [])) dreierListe'' = 3 : 2 : 1 : [] dreierListe''' = [3, 2, 1] -- Listen Kurzschreibweisen bis10 = [1..10] unendlicheListe = [1..] gerade = [2,4..] bis10' = take 10 unendlicheListe --Pattern Matching mit Listen or',or'' :: [Bool] -> Bool or' [] = False or' (x : xs) | (x==True) = True | otherwise = or' xs --Pattern Matching mit Listen und geschachtelten Mustern or'' [] = False or'' (True : _) = True or'' (False : xs) = or'' xs -- lokale definitionen / Funktionsschachtelung (where und let) -- (Beispiel übertragen aus "scala by example") wurzel :: Double -> Double wurzel x = iterWurzelF 1.0 x where gutGenugF s x = abs (s ^^ 2 - x) < 0.001 besserF s x = (s + x / s) / 2 iterWurzelF s x = if gutGenugF s x then s else iterWurzelF (besserF s x) x -- -> lokale Funktionen global nicht sichtbar -- Funktionsschachtelung 2: wurzel' :: Double -> Double wurzel' x = iterWurzelF 1.0 where iterWurzelF s = let gutGenug = abs (s ^^ 2 - x) < 0.001 besser = (s + x / s) / 2 in if gutGenug then s else iterWurzelF besser -- -> Argumente sparen die bereits sichtbar sind --Funktionen höherer Ordnung (mit Funktionsparameter oder Funktionsergebnis) -- 2.Version Liste gerader Zahlen zu erzeugen: Filtern gerade' :: [Int] gerade' = nimmGeradeF unendlicheListe --direkte Implementierung von nimmGeradeF nimmGeradeF :: [Int] -> [Int] nimmGeradeF [] = [] nimmGeradeF (x:xs) | istGerade x = x : nimmGeradeF xs | otherwise = nimmGeradeF xs --Parameterfunktion istGerade :: Int -> Bool istGerade x = (x `mod` 2 == 0) --1. Funktion höherer Ordnung: filter filter :: (a -> Bool) -> [a] -> [a] --aus Data.List filter _pred [] = [] filter pred (x:xs) | pred x = x : filter pred xs | otherwise = filter pred xs --nimmGeradeF mit Filter nimmGeradeF' :: [Int] -> [Int] nimmGeradeF' xs = filter istGerade xs --Argument kann weggelassen werden (Rückgabe ist Funktion die die Liste noch bekommt) nimmGeradeF'' :: [Int] -> [Int] nimmGeradeF'' = filter istGerade -- 3.Version Liste gerader Zahlen zu erzeugen: Multiplizieren gerade'' :: [Int] gerade'' = mal2F unendlicheListe mal2F :: [Int] -> [Int] mal2F [] = [] mal2F (x:xs) = (2 * x) : mal2F xs --2. Funktion höherer Ordnung: map map :: (a -> b) -> [a] -> [b] map _ [] = [] map f (x:xs) = f x : map f xs mal2F' :: [Int] -> [Int] mal2F' xs = map (*2) xs --Summen von Integerlisten mySum :: [Int] -> Int mySum [x] = x mySum (x:xs) = x + mySum xs mySum [] = error "mySum emptyList" --3. Funktion höherer Ordnung: foldr1 foldr1 :: (a -> a -> a) -> [a] -> a foldr1 _ [x] = x foldr1 f (x:xs) = f x (foldr1 f xs) foldr1 _ [] = error "errorEmptyList foldr1" mySum' :: [Int] -> Int mySum' = foldr1 (+) -- Lambda Abstraktionen (anonyme Funktionen) -- Liste gerader Zahlen ohne Hilfsfunktion gerade''' :: [Int] gerade''' = filter (\x -> x `mod` 2 == 0) unendlicheListe -- parameter -> Funktionskörper --Typ Aliase (nur Benennung) type Zahl = Int type Zahlenstrom = [Int] type Strom a = [a] type Zahlenstrom' = Strom Int --Typ Definitionen --Monomorph data SinglePaar = Paar Int Int | Single Int --Polymorph data SinglePaar' a b c = Paar' a b | Single' c type SinglePaar'' = SinglePaar' Int Int Int --Rekursiv (geht nicht mit type) data BinTree a = Leaf a | Node (BinTree a) a (BinTree a) deriving Show mkTree :: Int -> Int -> BinTree Int mkTree 1 n = Leaf n mkTree i n | (i<1) = error "tree without levels" | otherwise = Node (mkTree (i-1) (n-1)) n (mkTree (i-1) (n+1)) --Pattern Matching Beispiel inorderTraversal :: BinTree a -> [a] inorderTraversal (Leaf x) = [x] inorderTraversal (Node t1 x t2) = inorderTraversal t1 ++ x : inorderTraversal t2 --Typ Klassen (ähnlich zu Interfaces) {- Prelude> :i Eq class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool -} instance Eq a => Eq (BinTree a) where (Node _ _ _) == (Leaf _) = False (Leaf _) == (Node _ _ _) = False (Leaf a) == (Leaf b) = a == b -- Prüfe Elemente von Typ a (Node a1 x a2) == (Node b1 y b2) = x==y && -- Prüfe Elemente von Typ a a1==b1 && a2==b2 -- Prüfe rekursiv --Main main :: IO() main = do putStrLn "Level?" -- putStrLn :: String -> IO () level <- getLine --getLine :: IO String, level :: String wert <- putStrLn "Startwert?" wert <- getLine let t1 = mkTree (read level) (read wert) t2 = mkTree (read level) (read wert) putStrLn $ "Aequivalenztest sagt: " ++ ( show $ t1 == t2)