Programmieren in Haskell Ein- und Ausgabe Peter Steffen Universität Bielefeld Technische Fakultät 15.12.2010 1 Programmieren in Haskell Der Typ IO mit Hilfe des abstrakten Typs ‘IO val’ werden Aktionen beschrieben, die Ein- oder Ausgaben vornehmen. Allgemeiner: ..., die mit dem Betriebssystem oder der Umgebung kommunizieren. Ein Element vom Typ ‘IO val’ beschreibt eine EA-Aktion, die einen Wert vom Typ ‘val’ zurückgibt. 2 Programmieren in Haskell Vordefinierte Ausgabefunktionen putChar putStr putStrLn print :: :: :: :: Char -> IO () String -> IO () String -> IO () (Show a) => a -> IO () putChar gibt ein einzelnes Zeichen aus putStr gibt einen String aus putStrLn gibt einen String gefolgt von einem Zeilenumbruch aus print wendet erst die show-Funktion auf die Eingabe an und gibt das Ergebnis aus 3 Programmieren in Haskell Vordefinierte Eingabefunktionen getChar getLine :: IO Char :: IO String getChar liest ein einzelnes Zeichen ein getLine liest einen String ein 4 Programmieren in Haskell Vordefinierte Operationen auf Dateien type FilePath = readFile writeFile appendFile String :: FilePath -> IO String :: FilePath -> String -> IO () :: FilePath -> String -> IO () readFile liest den Inhalt einer Datei ein und gibt diesen als String zurück writeFile schreibt einen String in eine Datei appendFile hängt einen String an eine Datei an 5 Programmieren in Haskell Verknüpfung von EA-Aktionen So geht es nicht: result = getLine ++ getLine Hier wäre nicht klar, in welcher Reihenfolge die beiden getLine-Funktionen verarbeitet würden. 6 Programmieren in Haskell Verknüpfung von EA-Aktionen return (>>) (>>=) :: a -> IO a :: IO a -> IO b -> IO b :: IO a -> (a -> IO b) -> IO b return verpackt einen Wert in den IO-Typ >> hängt zwei IO-Aktionen hintereinander >>= hängt zwei IO-Aktionen hintereinander und übergibt das Ergebnis der ersten an die zweite 7 Programmieren in Haskell Beispiel askFor askFor s io1 io1 8 :: String -> IO String = putStr s >> getLine :: IO () = askFor "filename: " readFile file putStr cnts Programmieren in Haskell >>= \file -> >>= \cnts -> Syntaktischer Zucker: do - Notation io = f g x h y >>= \x -> >>= \y -> ist gleichbedeutend mit io = do x <- f y <- g x h y 9 Programmieren in Haskell Syntaktischer Zucker: do - Notation askFor askFor s 10 :: String -> IO String = putStr s >> getLine io1 io1 :: IO () = askFor "filename: " readFile file putStr cnts io2 io2 :: IO () = do file <- askFor "filename: " cnts <- readFile file putStr cnts Programmieren in Haskell >>= \file -> >>= \cnts -> Kommandozeilenparameter getArgs :: IO [String] getArgs liefert die Liste der Kommandozeilenparameter import System main :: IO () main = do args <- getArgs cat args cat :: [String] -> IO () cat [] = return () cat (f:fs) = do cnts <- readFile f putStr cnts cat fs Start mit: runhugs cat.lhs file1 file2 11 Programmieren in Haskell Kompilieren mit dem ghc ghc = Glasgow Haskell Compiler jedes Programm muss eine main-Funktion enthalten. Diese wird beim Programmstart aufgerufen Beispiel: ghc -make ea.lhs -o ea Aufruf: ./ea fileA fileB 12 Programmieren in Haskell Beispiel module Main where import System main = do [inp, out] <- getArgs process inp out process inp out = do putStrLn ("reading " ++ inp) cnts <- readFile inp putStrLn "reversing" reversed <- return (reverse cnts) putStrLn ("writing " ++ out) writeFile out reversed 13 Programmieren in Haskell