Wir implementieren eine Matrixkomprimierungsbibliothek, die auf einer modifizierten zweidimensionalen Grammatiksyntax basiert. Jetzt haben wir zwei Ansätze für unsere Datentypen: Welcher ist bei Speichernutzung besser? (wir wollen etwas komprimieren;)).
Die Grammatiken enthalten NonTerminals mit genau 4 Produktionen oder ein Terminal auf der rechten Seite. Wir benötigen die Namen der Produktionen für Gleichheitsprüfungen und Grammatikminimierung.
Der Erste:
-- | Type synonym for non-terminal symbols
type NonTerminal = String
-- | Data type for the right hand side of a production
data RightHandSide = DownStep NonTerminal NonTerminal NonTerminal NonTerminal | Terminal Int
-- | Data type for a set of productions
type ProductionMap = Map NonTerminal RightHandSide
data MatrixGrammar = MatrixGrammar {
-- the start symbol
startSymbol :: NonTerminal,
-- productions
productions :: ProductionMap
}
Hier speichern unsere RightHandSide-Daten nur String-Namen, um die nächsten Produktionen zu bestimmen, und wir wissen hier nicht, wie Haskell diese Strings speichert. Zum Beispiel hat die Matrix [[0, 0], [0, 0]] 2 Produktionen:
a = Terminal 0
aString = "A"
b = DownStep aString aString aString aString
bString = "B"
productions = Map.FromList [(aString, a), (bString, b)]
Die Frage hier ist also, wie oft der String "A" wirklich gespeichert wird. Einmal in aString, 4 mal in b und einmal in Produktionen oder nur einmal in aString und die anderen haben nur "billigere" Referenzen?
Der Zweite:
data Production = NonTerminal String Production Production Production Production
| Terminal String Int
type ProductionMap = Map String Production
hier ist der Begriff "Terminal" etwas irreführend, weil es eigentlich die Produktion ist, die ein Terminal als rechte Seite hat. Die gleiche Matrix:
a = Terminal "A" 0
b = NonTerminal "B" a a a a
productions = Map.fromList [("A", a), ("B", b)]
und die ähnliche Frage: Wie oft wird die Produktion von Haskell intern gespeichert? Möglicherweise werden wir die Namen in den Produktionen ablegen, wenn wir sie nicht brauchen, aber wir sind uns derzeit nicht sicher.
Nehmen wir also an, wir haben eine Grammatik mit ungefähr 1000 Produktionen. Welcher Ansatz verbraucht weniger Speicher?
Zum Schluss noch eine Frage zu ganzen Zahlen in Haskell: Derzeit planen wir, einen Namen als Strings zu haben. Aber wir könnten leicht zu ganzzahligen Namen wechseln, da wir bei 1000 Produktionen Namen mit mehr als 4 Zeichen haben (von denen ich annehme, dass sie 32 Bit sind?). Wie geht Haskell damit um? Weist ein Int immer 32 Bit und Integer Speicher zu, den es wirklich benötigt?
Ich habe auch Folgendes durchgelesen : Entwickeln eines Tests der Wert- / Referenzsemantik von Haskell - aber ich kann nicht herausfinden, was das genau für uns bedeutet - ich bin eher ein zwingendes Java-Kind als ein guter funktionaler Programmierer: P.