Eine funktionale Programmiersprache
filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter pred (x:xs)
| pred x = x : filter pred xs
| otherwise = filter pred xsString, Int, LT, Numfun x = x * xsort :: Ord a => [a] -> [a]-- "{- -}"{- Kommentar-Block {- innerer Block -} wieder äußerer Block -}"let c = 'a' -- Typ Charlet s = "abc" -- Typ String, bzw. [Char]let i = 0 -- Typ Intlet i = 0 :: Integer -- Typ Integerlet d = 0.0 -- Typ Doublelet d = 0 :: Double -- Typ Doublelet b = True -- Typ Bool, Gegenteil: Falselet l = [1,2,3,4] -- Typ [Int]let l = [1..10] -- Kurzform einer Listelet infinite = [1..] -- unendliche Liste (lazy)let t = (1,"abc") -- Typ (Int, String)let newList = newElement : listlet new List = list ++ [newElement]filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter pred (x:xs)
| pred x = x : filter pred xs
| otherwise = filter pred xs
data Day =
Monday
| Tuesdays
| Wednesdays
| Thursday
| Friday
| Saturday
| Sundaydata Person =
Person String Inttype Name = String
type Age = Intdata Person = Person Name Agelet person = Person "SDK" 30Wie kommen wir an die Eigenschaften heran?
getName (Person n _) = n
getAge (Person _ a) = aGeht das noch besser/einfacher?
data Person = Person
{ name :: String
, age :: Int
}let p = Person "SDK" 30
let p = Person
{ name = "SDK"
, age = 30
}Accessoren:
name :: Person -> Name
age :: Person -> AgeVorteile:
let newPerson =
p { name = "Flo" }Nachteil:
data Person =
Person
{ name :: Name
, age :: Age
}
data Dog =
Dog
{ name :: Name
, age :: Age
}Lösung:
"OverloadedRecordFields" (Language-Extension)
-- wird vom Compiler in Int umgewandelt
newtype Natural = MkNatural IntDatentypen sind lazy per default, können aber mit dem strictness-flag ("!") als non-lazy bzw. strict deklariert werden. Beispiel:
data RealFloat a => Complex a = !a :+ !a
Strictness in Funktionen mit "seq" oder "!$".
a" muss eine Instanz der Typ-Klasse "Ord" sein (muss also sortierbar sein)fun :: a -> bcompare :: Ord a => a -> a -> OrderingKlassische Funktionen:
mult (a,b) = a*bHaskell-Funktionen:
mult a b = a*bmultBy2 = mult 2
-- oder:
multBy2 = (*2)Currying:
Lambda-Ausdrücke:
mult = \a b -> a*b
map2 = map (\a -> a * 2)
-- kürzer:
map2 = map (*2)List-Concatanation:
infixr 5 ++
(++) :: [a] -> [a] -> [a]
(++) [] ys = ys
(++) (x:xs) ys = x : xs ++ ysFunction Composition:
infixr 9 .
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)let a = (+) 2 3let a = 2 `mult` 3infix[l/r] n operatorBeispiel:
infixl 7 *
infixl 6 +, -
infixr 0 $contrived :: ([a], Char, (Int, Float), String, Bool) -> Bool
contrived ([], 'b', (1, 2.0), "hi", True) = FalseAs-Pattern:
f (x:xs) = x:x:xs
-- geht kürzer
f s@(x:xs) = x:s -- s == x:xs
fib@(1:tfib) = 1 : 1 : [ a+b | (a,b) <- zip fib tfib ]Wild-Cards:
head (x:_) = x
tail (_:xs) = xssign x | x > 0 = 1
| x == 0 = 0
| x < 0 = -1let s = "1"
let default n = 0
let n = case reads s of
[(n,_)] -> n
_ -> 0checkPrefix s con action next =
let (pre, post) = T.splitAt (T.length s) con
in if pre == s then action post else nextf x y | y > z = ...
| y == z = ...
| y < z = ...
where z = x*xderive (Eq, Read, Show)getChar :: IO Char
readFile :: FilePath -> IO Char
-- type FilePath = StringputChar :: Char -> IO () -- () ~= void
putStrLn :: String -> IO ()
writeFile :: FilePath -> String -> IO ()Von IO:
Nach IO:
main :: IO ()
main = do
c <- getChar
if c == 'y'
then return ()
else mainpublic static void main( String[] args )Vgl:
IO im Rückgabewert sind IO-Actionsdo-Notation kann angewandt werdenIO-Actions enthaltenDebug.Trace
do { a <- f ; m } ≡ f >>= \a -> do { m }
do { f ; m } ≡ f >> do { m }
do { m } ≡ mdo {
a <- f ;
b <- g ;
c <- h ;
return (a, b, c)
}
f >>= \a ->
g >>= \b ->
h >>= \c ->
return (a, b, c)(>>=) :: Monad m => m a -> (a -> m b) -> m b
(>>) :: Monad m => m a -> m b -> m bputStr :: String -> IO ()
putStr = mapM_ putChar
putStr' = foldr ((>>) . putChar) (return ())
putStrLn' s = putStr s >> putChar '\n'