Ich lese gerade das Buch „Get Programming with Haskell“ und erstelle kleine Übungsprogramme, um Haskell auszuprobieren.
Die Aufgabe, die ich hier beschreibe, ist es eine einfache Konsolenanwendung zu schreiben, die eine Multiplikationstabelle berechnet und ausgibt.
So etwas in z.B. Java zu implementieren ist sehr einfach, da man einfach zwei Schleifen ineinander schachteln kann. Da Haskell eine rein funktionale Sprache ist, gibt es leider keine einfachen Schleifen, geschweige denn veränderbare (Schleifen-)Variablen.
Ich stelle hier zwei verschiedene Lösungen vor: Eine mit Map/Lambda und eine mit List Comprehensions.
Zuerst die mit Map/Lambda:
1 2 3 4 5 6 7 8 9 10 11 |
import Text.Printf (printf) row :: String -> Int -> String row prefix r = prefix ++ mconcat (map (\c -> printf "%4d" (r * c)) [1 .. 10]) ++ "\n" table :: String table = row " " 1 ++ mconcat (map (\r -> row (printf "%4d" r) r) [1 .. 10]) main :: IO () main = do putStr table |
Und hier die Version mit List Comprehensions:
1 2 3 4 5 6 7 8 9 10 11 |
import Text.Printf (printf) row :: String -> Int -> String row prefix r = prefix ++ mconcat [printf "%4d" (r * c) | c <- [1 .. 10]] ++ "\n" table :: String table = row " " 1 ++ mconcat [row (printf "%4d" r) r | r <- [1 .. 10]] main :: IO () main = do putStr table |
Wie man sieht, unterscheiden sich die beiden Programme an den Stellen, an denen Listen erstellt werden. Der Codeabschnitt:
1 |
(map (\c -> printf "%4d" (r * c)) [1 .. 10]) |
erstellt eine Liste bestehend aus 4 Zeichen breiten Strings, die die Ergebnisse der Multiplikation von r (Row) mit c (Column) als rechtsbündige Strings darstellen. Also [“ 1″, “ 2″,…,“ 10″]. Mit mconcat werden die Strings in dieser Liste dann zu einem einzigen String verkettet.
In der Version mit List Comprehension sieht der Codeabschnitt so aus:
1 |
[printf "%4d" (r * c) | c <- [1 .. 10]] |
Mir persönlich gefällt die Version mit List Comprehension besser, da sie einfacher zu lesen ist und viel schöner und klarer aussieht.