Typen von Funktionen
Next:FunktionsdefinitionenUp:Grundlegende SprachelementePrevious:Typen
Typen von Funktionen
- higher order functions
= Funktionen mit Funktionen als Argument und Resultat
z.B. (numerische) Differentiation:
diff :: (Float -> Float) -> (Float -> Float)
diff f = g
where g x = ( f (x + delta) - f x ) / delta
delta = 0.001
( Obacht: Beispiel ist numerisch nicht das Feinste! )
> diff sin 0
1.0
> diff cos (pi/2)
-1.00005
>diff (diff cos) 0 - 2. Ableitung
-1.07288
Beachte Bindekraft und Linksassoziierung von Funktionsanwendung!
diff sin 0 - ist (diff sin) 0,
- und diff sin :: Float -> Float
- ( => :type Kommando!)
Sowas wie
diff diff cos 0
wird deshalb gegliedert zu
(diff diff) cos 0
und ergibt Typfehler!
- Currying
[Anm.: ( Konzept aus der Mathematischen Logik & Grundlagenforschung; erfunden von Schönfinkel, popularisiert durch Haskell Curry ) ]
Funktionen mit mehreren Argumenten werden meist aufgefaßt als Funktionen mit Tupel als Argument, z.B.:
Volumen :: ( R R R ) R
(länge, breite, höhe) länge * breite * höheHaskell benutzt andere und äquivalente Auffassung:
volume :: Float->Float->Float->Float
volume l b h = l*b*h
deren besonderer Nutzen darin liegt, daß die Argumente sukzessive einzeln kommen können d.h. partielle Funktionsanwendung ist möglich (und ergibt natürlich eine Funktion der restlichen Argumente!):
> volume 1 1
<< Function >>
> :type volume 1 1
volume 1 1 :: Float -> Float
Die durch partielle Anwendung resultierende Funktion läßt sich wie üblich verwenden, z.B.:
> diff (volume 1 1) 47.11
0.949451
und zur Bequemlichkeit auch mit einem Namen versehen, z.B.:
volume_per_unitsquare = volume 1 1
- anderes Beispiel:
- Differentiation mit variierbarer Genauigkeit:
multi_diff :: Float -> (Float -> Float) -> (Float -> Float)
multi_diff d f x = (f (x+d)- f x) / d
dann kann man definieren:
coarse_diff = multi_diff 10.0
fine_diff = multi_diff 1.0e-3 - nicht zu klein machen!!
und rechnen:
> coarse_diff cos (pi/2)
0.0544021
> fine_diff cos (pi/2)
-1.00005
Damit partielle Anwendung funktioniert, müssen Funktionstypen nach rechts assoziieren:
volume :: Float -> Float -> Float -> Float
- ist: Float -> (Float -> (Float -> Float))
multi_diff :: Float -> (Float -> Float) -> (Float -> Float)
- ist Float -> ((Float -> Float) -> (Float -> Float))
Hier noch mal ausführliche Beispiele:
----------------POLYMORPHISM, list-type examples
Prelude> :type []
[] :: [a]
Prelude> :type (:)
(:) :: a -> [a] -> [a]
Prelude> :type 'a':[]
'a' : [] :: [Char]
Prelude> 'a':[]
"a"
Prelude> :type ['a','b','c']:[]
['a','b','c'] : [] :: [[Char]]
Prelude> ['a','b','c']:[]
["abc"]
Prelude> :type ['a','b','c']:['a','b','c']
ERROR: Type error in application
*** expression : ['a','b','c'] : ['a','b','c']
*** term : ['a','b','c']
*** type : [Char]
*** does not match : Char
Prelude> :type ['a','b','c']:[['a','b','c']]
['a','b','c'] : [['a','b','c']] :: [[Char]]
Prelude> ['a','b','c']:[['a','b','c']]
["abc", "abc"]
Prelude> :type length
length :: [a] -> Int
Prelude> length []
0
Prelude> length ['a']
1
Prelude> length [1000, 10000]
2
Prelude> length ( ['a','b','c']:[['a','b','c']])
2
----------HIGHER ORDER FUNCTION EXAMPLE
tabulate :: Float->Float->Int->(Float->Float)->[Float]
tabulate start step times f
|times <=0 = []
|otherwise = (f start):(tabulate (start+step) step (times-1) f)
Main> tabulate (-1) 0.2 11 sin
[-0.841471, -0.717356, -0.564642, -0.389418, -0.198669, -2.98023e-08,
0.198669, 0.389418, 0.564642, 0.717356, 0.841471]
Main> :type diff
diff :: Fractional a => (a -> a) -> a -> a
Main> :type (diff cos)
diff cos :: Floating a => a -> a
Main> tabulate (-1) 0.2 11 (diff cos)
[0.8412, 0.716984, 0.564218, 0.38898, 0.198126, -0.000476837, -0.199199,
-0.389874, -0.565052, -0.717699, -0.841737]
Main> let around_zero = tabulate (-1) 0.2 11 in around_zero sin
[-0.841471, -0.717356, -0.564642, -0.389418, -0.198669, -2.98023e-08,
0.198669, 0.389418, 0.564642, 0.717356, 0.841471]
Next:FunktionsdefinitionenUp:Grundlegende SprachelementePrevious:Typen Ronald Blaschke
1998-04-19