Hoed-0.2.0: examples/Hashmap.hs
{-# LANGUAGE DeriveGeneric #-}
import Prelude hiding (lookup,insert)
import Data.Maybe (fromJust)
import Debug.Hoed
--------------------------------------------------------------------------------
data Hashmap a = Hashmap Int [(Maybe a)] deriving Generic
class Hashable a where hash :: a -> Int
emptyMap :: Int -> Hashmap a
emptyMap size = Hashmap size $ take size (repeat Nothing)
size :: Hashmap a -> Int
size (Hashmap s _) = s
(%) :: Int -> Hashmap a -> Int
idx % hashmap = idx `mod` (size hashmap)
(!!!) :: Hashmap a -> Int -> Maybe a
(!!!) (Hashmap _ elems) = (!!) elems
(///) :: Hashmap a -> (Int,Maybe a) -> Hashmap a
(Hashmap size elems) /// e = Hashmap size (elems // e)
(//) :: [a] -> (Int,a) -> [a]
xs // (idx,x) = take idx xs ++ x : (drop (idx + 1) xs)
add :: (Observable k, Observable v, Hashable k)
=> (k,v) -> Hashmap (k,v) -> Hashmap (k,v)
add (key,elem) hashmap
= ( -- observe "add"
(\(key,elem) hashmap -> {-# SCC "add" #-}
let idx = (hash key) `mod` (size hashmap)
in insert hashmap idx (key,elem)
)
) (key,elem) hashmap
insert :: Hashmap a -> Int -> a -> Hashmap a
insert hashmap idx x = case hashmap !!! idx of
Nothing -> hashmap /// (idx,Just x)
_ -> insert hashmap ((idx+1) % hashmap) x
lookup :: (Observable k, Observable v, Eq k, Hashable k)
=> k -> Hashmap (k,v) -> Maybe (k,v)
lookup key hashmap
= (observe "lookup"
(\key hashmap -> {-# SCC "lookup" #-}
let idx = find hashmap ((hash key) % hashmap) key
in fmap (\i -> fromJust $ hashmap !!! i) idx
)
) key hashmap
find :: (Observable k, Observable v, Eq k)
=> Hashmap (k,v) -> Int -> k -> Maybe Int
find hashmap idx key
= ( observe "find"
(\hashmap idx key -> {-# SCC "find" #-}
case hashmap !!! idx of
Nothing -> Nothing
(Just (key',elem)) -> if key == key'
then Just idx
else find hashmap ((idx+1) % hashmap) key
)
) hashmap idx key
remove :: (Eq k, Hashable k, Observable k, Observable v)
=> k -> Hashmap (k,v) -> Hashmap (k,v)
remove key hashmap
= ( observe "remove"
(\key hashmap -> {-# SCC "remove" #-}
case find hashmap ((hash key) % hashmap) key of
Nothing -> hashmap
Just idx -> hashmap /// (idx,Nothing)
)
) key hashmap
instance Observable a => Observable (Hashmap a)
instance Observable Testval
instance Observable Testkey
--------------------------------------------------------------------------------
data Testkey = One | Two | Three deriving (Eq, Generic)
data Testval = Wennemars | Kramer | Verheijen deriving (Eq, Generic)
main = runO $ print test
instance Hashable Testkey where
hash One = 10
hash Two = 20
hash Three = 30
map1 :: Hashmap (Testkey,Testval)
map1 = ( (add (Two, Verheijen))
. (add (One, Kramer))
) (emptyMap 5)
-- test = lookup Two map1 == lookup Two (remove One map1)
test = (==) (observe "testLeft" $ {-# SCC "testLeft" #-} lookup Two map1 )
(observe "testRight" $ {-# SCC "testRight" #-} lookup Two (remove One map1))