The Haskell Hash-Consing Library provides efficient data structures and operations for hash-consing, allowing users to reuse common data structures while preserving maximum sharing. This technique can save memory and speed up equality comparisons.
-
Hash-Consed Data Structure (
HC)- A custom data type for hash-consed values.
-
Weak Reference Based Table (Using
HashConsModule)- Allows for potential garbage collection of unused values, freeing up memory.
-
Pure Version of Hash-Consing Table (Using
HashConsPureModule)- An alternative to the weak reference-based approach without garbage collection. Users need to manually maintain the table and ensure values are present in it before utilizing them.
-
Extensive Utility Functions
- Create, retrieve, and manage hash-consed values and their tables.
Users should be aware of the key differences and the recommended usage patterns of HashCons and HashConsPure:
-
HashCons: It is a derivable class and it is recommended to use constructors (as shown in the example below) for easy readability and maintainability of the code. -
HashConsPure: This is more of a table containing wrapped lookup of values. Users need to ensure values are present in it before utilizing hash-consed values. It's more manual in nature, giving users a granular control over hash-consing, at the cost of convenience.
To use the weak reference-based version of this library, import the HashCons module. For the pure version, import the HashConsPure module.
This section aims to offer users a clearer distinction between the two modules and how they are intended to be used.
import HashCons as hc
type Expr = hc.HC Expr'
data Expr' = Lit Int | Add Expr Expr deriving (Eq, Hashable, HashCons)
-- Constructors
lit :: Int -> Expr
lit val = hc.hashcons (Lit val)
add :: Expr -> Expr -> Expr
add exprL exprR = hc.hashcons (Add exprL exprR)
-- Hash-cons the expressions
hcExpr1 = add (lit 2) (lit 5)
hcExpr2 = add (lit 2) (lit 5)
-- Efficiently check for equality
print (hcExpr1 == hcExpr2) -- TrueFor the pure version, users need to maintain the hash-consing table and ensure that values are present in it before utilizing hash-consed values. If a value is not present in the table, it will not be hash-consed.
import HashConsPure as hcp
type Expr = hcp.HC Expr'
data Expr' = Lit Int | Add Expr Expr deriving (Eq, Hashable)
-- Creating a new table
myTable = hcp.newTable
-- Hash-cons the expressions
(hcExpr1, updatedTable) = hcp.hashCons (Lit 2) myTable
(hcExpr2, updatedTable) = hcp.hashCons (Lit 5) updatedTable
(hcExpr3, updatedTable) = hcp.hashCons (Add hcExpr1 hcExpr2) updatedTable
(hcExpr4, updatedTable) = hcp.hashCons (Add hcExpr1 hcExpr2) updatedTable
-- Efficiently check for equality
print (hcExpr3 == hcExpr4) -- TrueIn the pure version, the table just keeps growing even if certain values are no longer needed in the program. If users are certain that a value is no longer required, they can remove it with:
newTable = hcp.remove val updatedTableBe sure to hash-cons the value again using hashCons before performing any lookups or using the hash-consed value.
-
hashCons :: HashCons a => a -> HC a:- Hash-cons a value. If the value already exists in the table, returns the existing hash-consed value.
-
getValue :: HC a -> a:- Extract the actual value from a hash-consed value.
-
newTable :: Table a:- Create a new empty table for the pure version.
-
getValue :: HC a -> a:- Extract the actual value from a hash-consed value.
-
getKey :: HC a -> int:- Extract the hash key from a hash-consed value.
-
hashCons :: Hashable a => a -> Table a -> (HC a, Table a):- Hash-cons a value using the pure version of the table.
-
remove :: Hashable a => a -> Table a -> Table a:- Remove a value from the pure hash-consing table.
-
printTable :: Show a => Table a -> IO ():- Print the contents of a hash-consing table for the pure version.
-
What is hash-consing?
Hash-consing is a technique to maximize structural sharing by ensuring that identical data structures share memory.
-
Why use weak references?
Weak references allow unused hash-consed values to be garbage collected, freeing up memory.
Feel free to open issues or submit pull requests if you find bugs or have suggestions for improvements.
This library is provided under the BSD 3-Clause License. See LICENSE for details.