Você está na página 1de 50

F unktionale Programmierung mit Haskell

Jannis Harder

MetaNook 25. November 2011

Warum?

F unktionale Programmierung

F unktionen sind F unktionen


Und keine Prozeduren, Methoden, Befehle oder Anweisungen

F unktionen sind Werte


Genauso wie Zahlen, Listen, Texte, Bume, Bilder

Auer Werten
und damit auch F unktionen

gibt es nichts

Haskell

Erste Eindrcke

quicksort [] = [] quicksort (p:xs) = quicksort low ++ [p] ++ quicksort high where (low, high) = partition (< p) xs

primes = nubBy (\n p > n `mod` p == 0) [2..]

Anwenden von F unktionen


ghci> 5.0 ghci> 5 ghci> 23 ghci> 23 ghci> 5 ghci> 6 ghci> 5 sqrt 25 min 42 5 3 * 7 + 2 (+) ((*) 3 7) 2 345 `mod` 10 min 5 4 + 2 min 5 (4 + 2)

Booleans und Strings

Prelude> not True False Prelude> True && False False Prelude> True || False True Prelude> length "Foobar" 6 Prelude> reverse "!dlrow ,olleH" "Hello, world!"

Typen
Prelude> not "True" Couldn't match expected type `Bool' with actual type `[Char]' In the first argument of `not', namely `"True"' In the expression: not "True" Prelude> :type True True :: Bool Prelude> :t "True" "True" :: [Char] Prelude> :t not not :: Bool > Bool Prelude> :t not True not True :: Bool

Eigene Definitionen
definitions.hs
doubleMe x = x + x

Prelude> :load definitions.hs [1 of 1] Compiling Main Ok, modules loaded: Main. *Main> doubleMe 5 10

Alles neu definieren

tripleMe x = 3 * x

*Main> :reload Ok, modules loaded: Main. *Main> tripleMe 5 15 *Main> doubleMe 5 Not in scope: `doubleMe'

Mehr Argumente und Currying


implies a b = not a || b

*Main> :r *Main> True `implies` False False *Main> implies False False True *Main> (implies False) False True *Main> :t implies implies :: Bool > (Bool > Bool) *Main> :t implies False implies False :: Bool > Bool

Listen
*Main> [1,2,3,4] [1,2,3,4] *Main> 1:(2:(3:(4:[]))) [1,2,3,4] *Main> 1:2:3:4:[] [1,2,3,4] *Main> head [1,2,3,4] 1 *Main> tail [1,2,3,4] [2,3,4] *Main> ['F','o','o'] "Foo" *Main> [True, 'o'] Couldn't match expected type `Bool' with actual type `Char'

Maybe?

*Main> [Just 1, Nothing] [Just 1,Nothing] *Main> find (> 9000) [1,2,3] Nothing *Main> find (== 2) [1,2,3] Just 2 *Main> :t Just "something" Just "something" :: Maybe [Char]

Tupel
*Main> (True, 'o') (True,'o') *Main> :t (True, 'o') (True, 'o') :: (Bool, Char) *Main> fst (True, 'o') True *Main> snd (True, 'o') 'o' *Main> (False, '5', 23) (False, '5', 23)

Polymorphie
*Main> :t "Foo" "Foo" :: [Char] *Main> :t [True, True, False] [True, True, False] :: [Bool] *Main> :t [] [] :: [a] *Main> :t head head :: [a] > a *Main> :t (:) (:) :: a > [a] > [a] *Main> :t (,) (,) :: a > b > (a, b) *Main> :t fst fst :: (a, b) > a

Beschrnkte Polymorphie

*Main> 42 == 42 True *Main> "Foo" == "Bar" False *Main> '0' == "0" expected type `Char' actual type `[Char]' *Main> reverse == tail No instance for (Eq ([a0] > [a0]))

Typklassen

*Main> :t (==) (==) :: Eq a => a > a > Bool *Main> :info Eq class Eq a where (==) :: a > a > Bool (/=) :: a > a > Bool instance Eq Integer instance Eq Char instance Eq a => Eq [a] . . .

Mehr Listen
*Main> [1..5] [1,2,3,4,5] *Main> ['a'..'z'] "abcdefghijklmnopqrstuvwxyz" *Main> [ x^2 | x < reverse [1..5]] [25,16,9,4,1] *Main> [ x | x < [50..100], x `mod` 7 == 3] [52,59,66,73,80,87,94] *Main> [(x, y) | x < ["Foo", "Bar"], y < [1..3]] [("Foo",1),("Foo",2),("Foo",3), ("Bar",1),("Bar",2),("Bar",3)]

Pattern Matching
isEmptyList [] = True isEmptyList _ = False orElse (Just a) _ = a orElse Nothing b = b majority False False _ = False majority True True _ = True majority _ _ x = x end l = case reverse l of h : _ > h

Pattern Matching II

*Main> True *Main> 0 *Main> 9 *Main> '!'

isEmpty "" (find (>5) [1,2,3]) `orElse` 0 (find (>5) [9,8,7]) `orElse` 0 end "Haskell!"

If und Guards
sizeOfNumber x = if x > 9000 then "gigantisch" else "winzig" sizeOfNumber' x | x > 9000 = "gigantisch" | x < 100 = "winzig" | otherwise = "normal"

*Main> [sizeOfNumber x | x < [99, 999, 9999]] ["winzig","winzig","gigantisch"] *Main> [sizeOfNumber' x | x < [99, 999, 9999]] ["winzig","normal","gigantisch"]

Rekursion

selectNth 0 (h : _) = h selectNth n (_ : t) = selectNth (n 1) t fibonacci = 0 : 1 : [ a + b | (a, b) < zip fibonacci (tail fibonacci)]

F unktionen hherer Ordnung


*Main> succ 1 2 *Main> map succ [0,2,2,6] [1,3,3,7] *Main> :t map map :: (a > b) > [a] > [b] *Main> map (reverse . map succ) ["Foo", "Bar"] ["ppG","sbC"] *Main> :t (.) (.) :: (b > c) > (a > b) > a > c *Main> foldr (++) "!" ["Foo", "Bar", "Baz"] "FooBarBaz!"

F unktionen hherer Ordnung II


collatzStep x | x `mod` 2 == 0 = x `div` 2 | otherwise = 3 * x + 1 collatzSequence = takeWhile (> 1) . iterate collatzStep collatzNumber = length . collatzSequence

*Main> :t iterate iterate :: (a > a) > a > [a] *Main> :t takeWhile takeWhile :: (a > Bool) > [a] > [a] *Main> collatzSequence 11 [11,34,17,52,26,13,40,20,10,5,16,8,4,2] *Main> collatzNumber 27 111

-Ausdrcke und lokale Definitionen

*Main> map (\x > x ^ 3 x ^ 2) [1,2,3,4] [0,4,18,48] *Main> let f x = x ^ 3 x ^ 2 in map f [1,2,3,4] [0,4,18,48]

Eigene Datentypen
data Color = Red | Green | Blue | Orange deriving (Show, Read, Eq) data Size = XS | S | M | L | XL | XXL | XXXL deriving (Show, Read, Eq, Ord) data Shape = Circle Float | Rectangle Float Float | Polygon [(Float, Float)] deriving (Show, Eq) data Person = Person { name :: String , age :: Int } deriving (Show, Eq)

Eigene Datentypen II

*Main> [Red, Green, Blue] [Red,Green,Blue] *Main> Red == Green False *Main> [Circle 2.3, Rectangle 5 6] [Circle 2.3, Rectangle 5 6] *Main> name (Person "Jannis" 20) "Jannis"

Eigene polymorphe Datentypen

data OneOrTwo a = One a | Two a a deriving (Show, Eq, Ord) data List a = Empty | Cons a (List a) deriving (Show, Eq, Ord) data Tree a = Nil | Branch a (Tree a) (Tree a) deriving (Show, Eq, Ord)

Eigene polymorphe Datentypen

*Main> [One 1, Two 2 3] [One 1,Two 2 3] *Main> Two "Meta" "Meute" Two "Meta" "Meute"

Eigene Typklassen
class Empty a where empty :: a isEmpty :: a > Bool instance Empty [a] where empty = [] isEmpty [] = True isEmpty _ = False instance Empty (Tree a) where empty = Nil isEmpty Nil = True isEmpty _ = False

Eigene Typklassen

*Main> True *Main> False *Main> False *Main> Nil

isEmpty "" isEmpty [1,2,3] isEmpty (Branch 1 Nil Nil) empty :: Tree Int

F unctors
*Main> :info Functor class Functor f where fmap :: (a > b) > f a > f b instance Functor Maybe instance Functor [] *Main> fmap (+1) [1, 2] [2,3] *Main> fmap (+1) (Just 1) Just 2 *Main> fmap (+1) Nothing Nothing

Eigene F unktor-Instanzen

instance Functor OneOrTwo where fmap f (One a) = One (f a) fmap f (Two a b) = Two (f a) (f b) instance Functor Tree where fmap _ Nil = Nil fmap f (Branch a l r) = Branch (f a) (fmap f l) (fmap f r)

Eigene F unktor-Instanzen

*Main> fmap (*2) (One 1) One 2 *Main> fmap (*2) (Two 2 3) One 4 6 *Main> fmap (reverse) (Branch "Meta" (Branch "Meute" Nil Nil) Nil) Branch "ateM" (Branch "etueM" Nil Nil) Nil

Monads
*Main> :info Monad class Monad m where (>>=) :: m a > (a > m b) > m b return :: a > m a instance Monad Maybe instance Monad [] instance Monad IO

join :: Monad m => m (m a) > m a liftM :: Monad m => (a > b) > m a > m b m >>= f = join (liftM f m)

Monads II
foo l = l >>= \x > [2 * bar m = m >>= \x > if x then else x, 4 * x] > 10 return x 10 Nothing

*Main> foo [1,2,3] [2,4,4,8,6,12] *Main> foo (return 5) [10,20] *Main> bar Nothing Nothing *Main> bar (Just 5) Nothing *Main> bar (Just 20) Just 10

Do-Notation

foo l = do x < l [2 * x, 4 * x] bar m = do x < m if x > 10 then return x 10 else Nothing

Ein- und Ausgabe


*Main> getLine metameute "metameute" *Main> :t getLine getLine :: IO String *Main> putStrLn "metameute" metameute *Main> :t putStrLn putStrLn :: String > IO () *Main> getLine >>= putStrLn metameute metameute *Main> getLine >>= putStrLn . reverse metanook koonatem

Ein- und Ausgabe mit do-Notation


hier die collatz funktionen main = do handleOneInput main
handleOneInput = do n < readLn let sequence = collatzSequence n putStr "collatz sequence: " print sequence putStrLn "length: " print (length sequence)

Module

import import import import

Data.Maybe Data.List Data.Functor Control.Monad

Hilfe!

Buch: Learn You a Haskell for Great Good von Miran Lipovaa http://learnyouahaskell.com

Buch: Real World Haskell von Bryan OSullivan, Don Stewart und John Goerzen http://book.realworldhaskell.org/ Suchmaschine: Hayoo http://holumbus.fh-wedel.de/hayoo/hayoo.html Suchmaschine: Hoogle http://www.haskell.org/hoogle/ IRC: #haskell im F reeNode-Netzwerk.

Weitere funktionale Programmiersprachen

Lisp und Scheme

(let ((list '(print "Hello World"))) (print list) (eval list))

ML

fun fact (n) = if n=0 then 1 else n*fact(n1);

Scala

List(1,2,3,4,5) map {l => System.out.println(l) }

Erlang

http://goo.gl/ZYj64

Você também pode gostar