5.2. Hash

module Hash where

import Array

data Hash hash_function compare_function size table num_elems =
    MyHash hash_function compare_function size table num_elems

get_hash_function (MyHash hash_function compare_function size table num_elems) = hash_function

get_compare_function (MyHash hash_function compare_function size table num_elems) = compare_function

get_size (MyHash hash_function compare_function size table num_elems) = size

get_table (MyHash hash_function compare_function size table num_elems) = table

get_num_elems (MyHash hash_function compare_function size table num_elems) = num_elems

type IntHash = Hash (Int -> Int) (Int -> Int -> Int) Int (Array Int [(Int,Int)]) Int

type StringHash = Hash (String -> Int) (String -> String -> Int) Int (Array Int [(Int,String)]) Int

type StringToString = (String,String)

type StringToStringHash = Hash (StringToString -> Int) (StringToString -> StringToString -> Int) Int (Array Int [(Int,StringToString)]) Int

exists (MyHash hash_function compare_function size table num_elems) myelem =
    ((length
    (filter
        cmp_element
        (table!index)
    )) > 0) where
        hash_value = (hash_function myelem)
        index = (hash_value `mod` size)
        cmp_element x = (
                (hash_value == (fst x)) &&
                ((compare_function myelem (snd x)) == 0)
            )


insert (MyHash hash_function compare_function size table num_elems) myelem =
    (if (exists (MyHash hash_function compare_function size table num_elems) myelem)
    then (MyHash hash_function compare_function size table num_elems)
    else
    (MyHash
        hash_function
        compare_function
        size
        (table // [(index , new_list)])
        (num_elems+1)
    )) where
        hash_value = (hash_function myelem)
        index = (hash_value `mod` size)
        new_list = (hash_value,myelem):(table!index)

remove (MyHash hash_function compare_function size table num_elems) myelem =
    (MyHash
        hash_function
        compare_function
        size
        (table // [(index, new_list)])
        (if orig_len == length(new_list)
         then num_elems
         else (num_elems-1)
        )
    ) where
        hash_value = (hash_function myelem)
        index = (hash_value `mod` size)
        orig_len = length(table!index)
        cmp_element x = (
                (hash_value == (fst x)) &&
                ((compare_function myelem (snd x)) == 0)
            )
        new_list =
            (filter
                (\x -> (not(cmp_element x)))
                (table!index)
            )

get_value (MyHash hash_function compare_function size table num_elems) myelem =
    item_list where
        hash_value = (hash_function myelem)
        index = (hash_value `mod` size)
        cmp_element x = (
                (hash_value == (fst x)) &&
                ((compare_function myelem (snd x)) == 0)
            )
        item_list =
            [ snd(i) | i <- (filter cmp_element (table!index) ) ]

replace_or_add (MyHash hash_function compare_function size table num_elems) myelem =
    (MyHash
        hash_function
        compare_function
        size
        (table // [(index, new_list)])
        (if orig_len == length(new_list)
         then num_elems
         else (num_elems-1)
        )
    ) where
        hash_value = (hash_function myelem)
        index = (hash_value `mod` size)
        orig_len = length(table!index)
        cmp_element x = (
                (hash_value == (fst x)) &&
                ((compare_function myelem (snd x)) == 0)
            )
        new_list = (myreplace (table!index)) where
            myreplace :: [(Int,StringToString)] -> [(Int,StringToString)]
            myreplace [] = [(hash_value,myelem)]
            myreplace (a:as) =
                (if (cmp_element a)
                 then ((hash_value,myelem):as)
                 else (a:myreplace(as)))

get_all_values (MyHash hash_function compare_function size table num_elems) =
    [ snd(a) | i <- [ 0 .. (size-1) ] , a <- table!i ]

rehash (MyHash hash_function compare_function size table num_elems) new_size =
    (MyHash
        hash_function
        compare_function
        new_size
        new_table
        num_elems
    ) where
        new_table = (accumArray
            (\present -> \new_elem -> (new_elem:present))
            ]
            (0,(new_size-1))
            [   (hash_value `mod` new_size, (hash_value,elem)) |
                i <- [ 0 .. (size-1) ],
                (hash_value,elem) <- table!i
            ]
        )

Written by Shlomi Fish