Haskell for Perl ProgrammersArraysHash

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