Estamos implementando una biblioteca de compresión matricial basada en una sintaxis gramatical bidimensional modificada. Ahora tenemos dos enfoques para nuestros tipos de datos: ¿cuál será mejor en caso de uso de memoria? (Queremos comprimir algo;)).
Las gramáticas contienen No Terminales con exactamente 4 Producciones o una Terminal en el lado derecho. Necesitaremos los nombres de Producciones para verificaciones de igualdad y minimización gramatical.
El primero:
-- | 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
}
Aquí, nuestros datos RightHandSide guardan solo los nombres de cadenas para determinar las próximas producciones, y lo que no sabemos aquí es cómo Haskell guarda estas cadenas. Por ejemplo, la matriz [[0, 0], [0, 0]] tiene 2 producciones:
a = Terminal 0
aString = "A"
b = DownStep aString aString aString aString
bString = "B"
productions = Map.FromList [(aString, a), (bString, b)]
Entonces, la pregunta aquí es ¿con qué frecuencia se guarda realmente la cadena "A"? ¿Una vez en aString, 4 veces en by una vez en producciones o solo una vez en aString y los otros solo tienen referencias "más baratas"?
El segundo:
data Production = NonTerminal String Production Production Production Production
| Terminal String Int
type ProductionMap = Map String Production
aquí el término "Terminal" es un poco engañoso porque en realidad es la producción la que tiene un terminal en el lado derecho. La misma matriz:
a = Terminal "A" 0
b = NonTerminal "B" a a a a
productions = Map.fromList [("A", a), ("B", b)]
y la pregunta similar: ¿con qué frecuencia Haskell guarda internamente la producción? Posiblemente eliminaremos los nombres dentro de las producciones si no los necesitamos, pero no estamos seguros de esto en este momento.
Digamos que tenemos una gramática con alrededor de 1000 producciones. ¿Qué enfoque consumirá menos memoria?
Finalmente una pregunta sobre enteros en Haskell: actualmente estamos planeando tener un nombre como Strings. Pero podríamos cambiar fácilmente a nombres enteros porque con 1000 producciones tendremos nombres con más de 4 caracteres (que supongo que es de 32 bits). ¿Cómo maneja Haskell esto? ¿Es un Int siempre de 32 bits e Integer asigna memoria que realmente necesita?
También leí esto: Diseño de prueba de la semántica de valor / referencia de Haskell, pero no puedo entender qué significa eso exactamente para nosotros. Soy más un niño imperativo de Java que un buen programador funcional: P
fuente