Estamos implementando uma biblioteca de compactação de matriz baseada em uma sintaxe gramatical bidimensional modificada. Agora, temos duas abordagens para nossos tipos de dados - qual será melhor em caso de uso de memória? (queremos compactar algo;)).
As gramáticas contêm NonTerminals com exatamente 4 Productions ou um Terminal no lado direito. Vamos precisar dos nomes de Productions para verificação de igualdade e minimização gramatical.
O primeiro:
-- | 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
}
Aqui, nossos dados RightHandSide salvam apenas nomes de String para determinar as próximas produções, e o que não sabemos aqui é como Haskell salva essas strings. Por exemplo, a matriz [[0, 0], [0, 0]] possui 2 produções:
a = Terminal 0
aString = "A"
b = DownStep aString aString aString aString
bString = "B"
productions = Map.FromList [(aString, a), (bString, b)]
Portanto, a questão aqui é com que frequência a string "A" é realmente salva? Uma vez em aString, 4 vezes em be uma vez em produções ou apenas uma vez em aString e os outros apenas têm referências "mais baratas"?
O segundo:
data Production = NonTerminal String Production Production Production Production
| Terminal String Int
type ProductionMap = Map String Production
aqui o termo "Terminal" é um pouco enganador, porque na verdade é a produção que tem um terminal no lado direito. A mesma matriz:
a = Terminal "A" 0
b = NonTerminal "B" a a a a
productions = Map.fromList [("A", a), ("B", b)]
e a pergunta semelhante: com que frequência a produção é salva internamente por Haskell? Possivelmente colocaremos os nomes dentro das produções se não precisarmos deles, mas não temos certeza no momento.
Digamos que tenhamos uma gramática com cerca de 1000 produções. Qual abordagem consumirá menos memória?
Finalmente, uma pergunta sobre números inteiros em Haskell: Atualmente, estamos planejando ter o nome como Strings. Mas poderíamos facilmente mudar para nomes inteiros porque, com 1000 produções, teremos nomes com mais de 4 caracteres (o que, suponho, é 32 bits?). Como Haskell lida com isso. Um Int sempre é de 32 bits e um número inteiro aloca a memória de que realmente precisa?
Também li o seguinte: Teste da semântica de valor / referência de Haskell - mas não consigo descobrir o que isso significa exatamente para nós - sou mais uma criança java imperativa do que um bom programador funcional: P