VL10 Funktionale Programmierung Notiz

Einführung

Haskell ist funktionale Programmiersprachen
Funktional

  • Ein-/Ausgaberelation, die beschreibt was getan werden soll
  • Zustandslos
  • keine Variablen außer den Parametern
  • Rekursion(statt Schleifen)

Einführung in Haskell

Konstante Funktionen

  • Deklaration(Signatur)
    Bezeichner :: Rückgabetyp
  • Definition(Implementierung)
    Bezeichner = Definition
    Funktion mit Parametern
    (Die Erklärung der Deklaration und Definition wird unten weggelassen)
  • Bezeichner:: Parametertyp-> Rückgabetyp
  • Bezeichner Parameter = Definition
    Closures闭合 mit Let
  • let expr in …

Rekursion

Imprativ: while
Funktional(Haskell): if … then …(Rekursionsanker) else …(Rekursion)

Pattern Matching
verschiedene Fälle unterschieden werden
Beispiel:
potenz x 0 = 1
potenz x n = x * (potenz x (n - 1))
Achtung: first-fit!

Tail Recursion(Endrekursion)
zusätzlicher Parameter für Zwischenergebnisse nötig
Beispiel:
potenztc x 0 s = s – Rekursionsanker
potenztc x n s = (potenztc x (n - 1) (x * s))
potenz x n = potenz x n 1 – Startwert

Lazy vs. Eager Evalution
lazy evalution oder “call-by-need”: Ausdrücke werden erst dann ausgewertet, wenn sie benötigt werden
Eager Evalution erzwungen:
$! (x * s)
Erzwingt Eager Evaluation von (x * s)

Rekursive Fibonacci-Funktion / Effiziente Fibonacci-Funktion
Beispiel:
fibe :: Int -> Int
fibe 0 = (1,1)
fibe 1 = (1,2)
fibe n = let (a, b) = fibe (n-1)
in (b, a+b)

Datentypen

Definition Produkttyp
data Point = Point Double Double
data Typ = Konstruktor Parameter

Definition Aufzählungstyp
ein Spezialfall des Summentyps
data Color = Red | Green | Blue

Definition Summentyp
data Shape = Circle{center::Point, radius::Double} | Square{anchor::Point, length::Double}

shape – Typ
Circle – Konstruktor
center – Selektor 选择器

**Dekonstruktion **解构

  • _ Wildcard, kann für nicht benötigte Parameter eingesetzt werden
  • Pattern matching geht über Konstruktoren
    Beispiel:
    size :: Shape -> Double
    size (Circle c r) = 3.14159 * r * r
    size (Square a l) = l * l
  • Dekonstruktion
    size s = case s of
    (Circle c r)-> 3.15169 * r * r
    (Square a l) -> l * l

Rekursive Datenstruktur: Liste
data IList = IList{element::Int, rest::IList} | Empty
erzeugen:
let l = (IList 1 (IList 2 (IList 3 (IList 4 Empty))))
Zugriff über die Selektoren:
element (rest (rest (l))) = 3
leere Listen beinhalten keine Elemente, kann nicht zugreifen werden

Definition Bäume
data ITree = INode Int ITree ITree | Empty
rekursiove Summentypen
doppelt rekursiv

Parameterisierte Datentypen
IList: Liste ganzer Zahlen
BList: Listen von Wahrheitswerten
CList: Listen von Zeichen
DList: Listen von Gleitkommazahlen

Liste
Parametrisierte Liste
data List a = List{element::a, rest::(List a)} | Empty

Der Listenkonstruktor
vordefiniert
data [a] = a:[a] | [ ]

Standard-Liste: 5:7:9:[ ] = [5, 7, 9]
Zeichenketten:
type String = [Char]
‘a’:‘b’:‘c’:[ ] = [‘a’, ‘b’, ‘c’] = “abc”

parametrisierte Tupel
data Pair a b = PairConstructor a b
Tupel sind mit runden Klammern vordefiniert:
(1, 4.0, ‘a’, True) :: (Int, Double, Char, Bool)

Einfache Operation für Paare und Listen

  • Paare(2-Tupel):
    fst :: (a, b) -> a
    snd :: (a, b) -> b
  • Listen:
    head :: [a] -> a
    tail :: [a] -> [a] – ohne das erste Element
    last :: [a] -> a
    init :: [a[ -> [a] – ohne das letzte Element
    null :: [a] -> Bool

weitere Funktionen auf Listen
length :: [a] -> Int

append :: [a] -> [a] -> [a]
als (++)-Operator vordefiniert

reverse :: [a] -> [a]
reverse [ ] = [ ]
reverse[x:xs] = reverse[xs] ++ [x]

Definition Bäume
data Tree a = Node a (Tree a) (Tree a) | Empty

Definition Maybe
data Maybe a = Just a | Nothing

  1. if … return … ; else return null;
    pattern matching
  2. if (… != null) return …; else return false;
    case … of
    just … -> …
    Nothing -> False

Funktionen höherer Ordnung

Funktionen können Argumente von Funktionen sein

Anonyme Funktionen
Beispiel:
/x -> x * x
Typsignatur (\x -> x * x) :: Num a => a -> a

currying
{f | f :: a -> b -> c}
{g | g :: (a, b) -> c}
f = curry g
g = uncurry f
In Haskell werden alle Funktionen als curried betrachtet.

Partial Application
das Anwenden einer Funktion auf eine nicht-ausreichende Menge von Argumenten
Funktion mit weniger Parametern
Beispiel:
add 5 :: Int -> Int
(add 5) y = 5 + y

Prefix- und Infixnotation

  • Operatoren
    addSeven x = 7 + x = (+) 7 x = (+7) x – infix prefix
  • Funktion
    subTen x = sub x 10 = x ‘sub’ 10 = (‘sub’ 10) x – prefix infix

weitere Beispiele

  • kommutativen Operatoren
    double = (2*)
    isZero = (==0)
    wrong = (&&False)
    succ = (1+)
  • nicht kommutativen
    half = (/2)
    over5 = (>5)
    prefix = (“TU”++)
    pred = (’sub‘ 1)

Komposition
(.) :: (b -> c) -> (a -> b) -> (a -> c)
f.g = \x -> f (g x)

even = (0==).(‘mod’ 2)
odd = not.even

Listenfunktionale

Listenfunktionale
map: Manipulieren
filter: Aussortieren
zip: Zusammenführen(zipWith)
reduce: Zusammenfassung(fold)

map
wendet eine Funktion auf alle Elemente einer Liste an

map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = (f x) : map f xs

Filter
sortiert Elemente nach einer vorgegebenen Definition aus

filter :: (a -> Bool) -> [a] -> [b]
filter _ [] = []
filter f (x:xs) = if (f x) then x : filter f xs
else filter f xs

Guards
filter f (x:xs)
| (f x) = x : filter f xs
| otherwise = filter f xs

Fold reduce
Rechtes Fold
foldr fasst die Elemente einer Struktur zu einem Wert zusammen

foldr :: (a -> b -> b) -> b -> [a] -> b
foldr _ z [] = z
foldr f z (x:xs) = f x (foldr f z xs)

Beispiel:
sum = foldr (+) 0
(foldr (+) 0) [] = 0
(foldr (+) 0) (x:xs) = x + ((foldr (+) 0) xs)

Linkes Fold
foldl :: (b -> a -> b) -> b -> [a] -> b
foldl _ z [] = z
foldl f z (x:xs) = foldl f (f z x) xs

ZipWith
führt zwei Listen mit Hilfe eines Funktionals zusammen

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith _ [] _ = []
zipWith _ _ [] = []
zipWith f (x:xs) (y:ys) = (f x y) : zipWith f xs ys

unzip

Typklassen

Definition Typklassen
deklarieren welche Funktionen für einen Typen definiert sein müssen, damit er eine Instanz der Typklasse ist.

class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool

Instanziierung von Typklassen
instance Eq Rat where

Beispiel Nummern
class Num a where
(+), (-), (*) :: a -> a -> a
negate, signum, abs :: a -> a
fromInteger :: Integer -> a

erben
von anderen Typklassen erben

class Eq a => Ord a where
(<), (<=), (>=), (>) :: a -> a -> Bool
max, min :: a -> a -> a

instance Eq a => Eq [a] where
[] == [] = True
(x:xs) == (y:ys) = x == y && xs == ys
xs == ys = False

Typklasse Show
class Show a where
show :: a -> [Char]

Typklasse Enum
class Enum a where
fromEnum :: a -> Int
toEnum :: Int -> a

Typklasse Foldable
Zusammenfassen von Elementen
die Liste ist die wichtigste Instanz von Foldable

Unendliche Listen

Ranges
Nachfolgerfunktion

range :: Enum a => a -> a -> [a]
range x y
| (fromEnum x) > (fromEnum y) = [ ]
| otherwise = x : range (succ x) y

List Comprehension
in Haskell sind ranges als list comprehension vordefiniert.
[1…5] = [1, 2, 3, 4, 5]

  • Schrittweite wird aus der Differenz der ersten Werte abgeleitet
    odds = [1, 3 … 9 ]
    sevenDown = [35, 28 … 0]
  • kombinieren und filtern
    roll7 = [(a, b)| a <- [1…6], b <- [1…6], a+b == 7]
  • offene Ranges
    [0…]

Die natürlichen Zahlen
nats :: [Int]
nats = 0 : map (1+) nats

take 2 nats = [0, 1]
drop 2 nats = [2, 3 …]

Liste aller Primzahlen

  1. schreibe alle natürlichen Zahlen ab 2 in einer Liste auf
  2. Behalte das erste Element aus der Liste als Primzahl p
  3. Entferne alle Vielfachen dieser Zahl aus der Restliste
  4. Wiederhole Schritt 2 mit der gefilterten Restliste
    sieve(p:as) = p:sieve(filter (\x -> (x ‘mod’ p) /= 0) as)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值