Programmieren in Haskell Stefan Janssen Programmieren in Haskell Arrays Tabellierung Felder Stefan Janssen Universität Bielefeld AG Praktische Informatik November 5, 2014 Felder: Datenstrukturen mit konstantem Zugriff Programmieren in Haskell “Felder” nennt man auch Arrays, Vektoren, Matrizen, ... “Konstanter Zugriff” heisst: Zugriff auf Elemente mit Aufwand unabhängig von der Größe der Datenstruktur. Gegenbeispiel Musik: Finden der n-ten Note erfordert Durchlauf der Datenstruktur in n oder mehr Schritten. Allerdings: Die Noten sind nicht nummeriert. Stefan Janssen Arrays Tabellierung Felder: Datenstrukturen mit konstantem Zugriff Programmieren in Haskell “Felder” nennt man auch Arrays, Vektoren, Matrizen, ... “Konstanter Zugriff” heisst: Zugriff auf Elemente mit Aufwand unabhängig von der Größe der Datenstruktur. Gegenbeispiel Musik: Finden der n-ten Note erfordert Durchlauf der Datenstruktur in n oder mehr Schritten. Allerdings: Die Noten sind nicht nummeriert. Besseres Gegenbeispiel: Listen – hier sind die Elemente ab 0 nummeriert ... Stefan Janssen Arrays Tabellierung Zugriff auf Listenelemente Programmieren in Haskell Stefan Janssen Listen beherbergen viele Elemente gleichen Typs. 1 2 1 2 Sequentielle Abarbeitung ist einfach und effizient, z.B. map f [] = [] map f ( x : xs ) = f x : map f xs Random Zugriff auf einzelne Elemente durch operator !! hängt von der Listenlänge ab: ( x : xs ) !! 0 = x ( x : xs ) !! n = xs !!( n -1) Abhilfe schafft der Datentyp Array a b Arrays Tabellierung Datentyp Array a b Programmieren in Haskell Arrays – auf Deutsch “Felder” Modul Data.Array stellt Datentyp Array a b und Funktionen darauf bereit a ist der Datentyp des Index, b der Elementtyp Operator ! für Element-Zugriff bietet effizienten Random-Access Indextyp erlaubt mehrere Dimensionen Funktion array liefert ein Array zurück Stefan Janssen Arrays Tabellierung Datentyp Array a b Programmieren in Haskell Arrays – auf Deutsch “Felder” Modul Data.Array stellt Datentyp Array a b und Funktionen darauf bereit a ist der Datentyp des Index, b der Elementtyp Operator ! für Element-Zugriff bietet effizienten Random-Access Indextyp erlaubt mehrere Dimensionen Funktion array liefert ein Array zurück 1 array : : ( I x a ) => ( a , a ) −> [ ( a , b ) ] −> Array a b 2 3 t = a r r a y ( low , h i g h ) l i s t _ o f _ e n t r i e s = . . . Stefan Janssen Arrays Tabellierung Datentyp Array a b Programmieren in Haskell Arrays – auf Deutsch “Felder” Modul Data.Array stellt Datentyp Array a b und Funktionen darauf bereit a ist der Datentyp des Index, b der Elementtyp Operator ! für Element-Zugriff bietet effizienten Random-Access Indextyp erlaubt mehrere Dimensionen Funktion array liefert ein Array zurück 1 array : : ( I x a ) => ( a , a ) −> [ ( a , b ) ] −> Array a b 2 3 t = a r r a y ( low , h i g h ) l i s t _ o f _ e n t r i e s = . . . 1 (!) :: ( Ix a ) = > Array a b -> a -> b Stefan Janssen Arrays Tabellierung Beispiel: 2D Array 1 2 3 > module A r r > where > import Data . Array Programmieren in Haskell > t a b l e : : Array ( Char , I n t ) I n t > t a b l e = array ( ( ’ a ’ , 0) , ( ’ c ’ , 2) ) > [ ( ( ’ a ’ , 0) , 0 ) , > ( ( ’ a ’ , 1) , 1 ) , > ( ( ’ a ’ , 2) , 2 ) , > ( ( ’b ’ , 0) , 3 ) , > ( ( ’b ’ , 1) , 4 ) , > ( ( ’ c ’ , 0) , 6 ) , > ( ( ’ c ’ , 1) , 7 ) , > ( ( ’b ’ , 2) , 5 ) , > ( ( ’ c ’ , 2) , 8 ) > ] Arrays Stefan Janssen 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 > access a b = table ! (a , b) > access2 = ( table !) Tabellierung Alternative Programmieren in Haskell Stefan Janssen Pattern Matching als Alternative für read-only Felder vs. Feldgröße Arrays Tabellierung Alternative Programmieren in Haskell Stefan Janssen Pattern Matching als Alternative für read-only Felder vs. Feldgröße Tabellierung Example 1 2 3 4 5 access access access access ... ’a ’ ’a ’ ’a ’ ’b ’ 0 1 2 1 Arrays = = = = 0 1 2 3 Beispiel: Umwandlung String in Char Array Programmieren in Haskell Stefan Janssen Arrays Tabellierung 1 2 3 > s 2 a : : S t r i n g −> Array I n t Char > s2a xs = l i s t A r r a y (0 , length xs − 1) xs Akkumulierende Arrays Programmieren 1 2 in Haskell Manchmal kann man die Einträge eines Feldes nicht auf einmal Stefan ausrechnen. Dafür gibt es die Funktion Janssen > accumArray :: Ix a = > Arrays ( b -> c -> b ) -> b -> (a , a ) -> [( a , c )] -> Array a b Tabellierung 3 4 5 akkumulierende Bereich Fkt . Startwert Ergebnis Elemente Akkumulierende Arrays Programmieren 1 2 in Haskell Manchmal kann man die Einträge eines Feldes nicht auf einmal Stefan ausrechnen. Dafür gibt es die Funktion Janssen > accumArray :: Ix a = > Arrays ( b -> c -> b ) -> b -> (a , a ) -> [( a , c )] -> Array a b Tabellierung 3 4 5 akkumulierende Bereich Fkt . Startwert Elemente Der Aufruf accumArray f s (lo,up) assocslist erlaubt fehlende wie mehrfache Auftreten des Indices in den Associations initialisiert alle Elemente mit dem Startwert s akkumuliert mehrfache Auftreten (i,x),...,(i,y),...,(i,z) in der Form (((s ‘f‘ x) ‘f‘ y) ‘f‘ z) in Element i Ergebnis Akkumulierende Arrays Programmieren in Haskell Stefan 1 2 3 Janssen Beispiel: Zählen der Buchstabenhäufigkeit in einem Text > frq :: String -> Array Char Int Arrays > frq t = accumArray (+) 0 ( ’A ’ , ’z ’) ( zip t ones ) Tabellierung > where ones = 1: ones Akkumulierende Arrays Programmieren in Haskell Stefan 1 2 3 1 2 3 4 Janssen Beispiel: Zählen der Buchstabenhäufigkeit in einem Text > frq :: String -> Array Char Int Arrays > frq t = accumArray (+) 0 ( ’A ’ , ’z ’) ( zip t ones ) Tabellierung > where ones = 1: ones Damit z.B. Arr > frq " abraham " ! ’a ’ 3 Arr > frq " abraham " ! ’U ’ 0 Tabellierung von Funktionen Gegeben eine Funktion, die aufwendig zu berechnen ist: 1 2 3 > sid : : I n t −> I n t > s i d x = ( x +1)∗( x −1)−(x −2)∗( x+2)+(x−round 3 . 1 ) Programmieren in Haskell Stefan Janssen Arrays Tabellierung Tabellierung von Funktionen Gegeben eine Funktion, die aufwendig zu berechnen ist: 1 2 3 > sid : : I n t −> I n t > s i d x = ( x +1)∗( x −1)−(x −2)∗( x+2)+(x−round 3 . 1 ) Programmieren in Haskell Stefan Janssen Arrays Tabellierung Wenn die Werte (aus einem bekannten Intervall) immer wieder gebraucht werden, nimmt man eine interne Tabelle 1 2 3 4 5 6 > fid : : I n t −> I n t > f i d = ( f ! ) where > f = array (0 ,100) > [ ( x , ( x +1)∗( x −1)−(x −2)∗( x+2)+(x−round 3 . 1 ) ) > | x <− [ 0 . . 1 0 0 ] ] Das funktioniert schneller, aber nur über dem vorgesehenen Intervall. Tabellierung von Funktionen Programmieren in Haskell Tabellierung ist eine allgemeine Technik. Können wir eine Funktion tabulate schreiben, die andere Funktionen in tabellierte Funktionen verwandelt? Was wäre ihr Typ? Stefan Janssen Arrays Tabellierung Tabellierung von Funktionen Programmieren in Haskell Tabellierung ist eine allgemeine Technik. Können wir eine Funktion tabulate schreiben, die andere Funktionen in tabellierte Funktionen verwandelt? Was wäre ihr Typ? 1 2 > t a b u l a t e : : ( I n t , I n t )−>( I n t −>a)−>( I n t −>a ) Stefan Janssen Arrays Tabellierung Tabellierung von Funktionen Programmieren in Haskell Tabellierung ist eine allgemeine Technik. Können wir eine Funktion tabulate schreiben, die andere Funktionen in tabellierte Funktionen verwandelt? Was wäre ihr Typ? 1 2 > t a b u l a t e : : ( I n t , I n t )−>( I n t −>a)−>( I n t −>a ) Und was muss sie tun? Wir fordern ∀ x, f: (tabulate f) x = f x – nur schneller! Stefan Janssen Arrays Tabellierung Tabellierung von Funktionen Programmieren in Haskell Tabellierung ist eine allgemeine Technik. Können wir eine Funktion tabulate schreiben, die andere Funktionen in tabellierte Funktionen verwandelt? Was wäre ihr Typ? 1 2 > t a b u l a t e : : ( I n t , I n t )−>( I n t −>a)−>( I n t −>a ) Und was muss sie tun? Wir fordern ∀ x, f: (tabulate f) x = f x – nur schneller! 1 2 3 > t a b u l a t e ( l o , up ) f = ( t ! ) where > t = a r r a y ( l o , up ) ( z i p domain (map f domain ) ) > domain = [ l o . . up ] Stefan Janssen Arrays Tabellierung Tabellierung von Funktionen Programmieren in Haskell Stefan Janssen Damit nun einfach – für beliebige Funktionen über einem Intervall, aber hier am Beispiel sid 1 2 3 > t i d : : I n t −> I n t > t i d = tabulate (1 ,100) s i d Betrachte die Anzahl der Rechenschritte bei mehrfachen Aufrufen von sid 42, fid 42, tid 42 ... Arrays Tabellierung