Skip to content

Commit

Permalink
Revert attempt at implementing fromList using mutation
Browse files Browse the repository at this point in the history
There's a better way that doesn't involve traversing and freezing the
tree in the end.

Reverts:

 * "Add a HashMap type that's mutable in ST"
 * "Implement formList[With] in terms using mutation"
 * "Add to-do"

This reverts commit 1bde20b.
  • Loading branch information
tibbe committed Mar 9, 2012
1 parent 31a07c2 commit 5bdb93a
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 345 deletions.
32 changes: 0 additions & 32 deletions Data/HashMap/Array.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ module Data.HashMap.Array
, updateWith
, insert
, insert'
, insertM
, delete
, delete'

Expand All @@ -45,7 +44,6 @@ module Data.HashMap.Array
, thaw
, map
, map'
, mapM'
, traverse
, filter
) where
Expand Down Expand Up @@ -276,19 +274,6 @@ insert' ary idx b =
where !count = length ary
{-# INLINE insert' #-}

-- | /O(n)/ Insert an element at the given position in this array,
-- increasing its size by one.
insertM :: MArray s e -> Int -> e -> ST s (MArray s e)
insertM mary idx b =
CHECK_BOUNDS("insertM", count + 1, idx)
do mary' <- new_ (count+1)
copyM mary 0 mary' 0 idx
write mary' idx b
copyM mary idx mary' (idx+1) (count-idx)
return mary'
where !count = lengthM mary
{-# INLINE insertM #-}

-- | /O(n)/ Update the element at the given position in this array.
update :: Array e -> Int -> e -> Array e
update ary idx b = runST (update' ary idx b)
Expand Down Expand Up @@ -377,23 +362,6 @@ map f = \ ary ->
go ary mary (i+1) n
{-# INLINE map #-}

-- TODO: We ought to be able to not copy the whole array.
mapM' :: (a -> ST s b) -> MArray s a -> ST s (MArray s b)
mapM' f = \ mary ->
let !n = lengthM mary
in do
mary' <- new_ n
go mary mary' 0 n
where
go mary mary' i n
| i >= n = return mary'
| otherwise = do
x <- read mary i
y <- f x
write mary' i $! y
go mary mary' (i+1) n
{-# INLINE mapM' #-}

-- | Strict version of 'map'.
map' :: (a -> b) -> Array a -> Array b
map' f = \ ary ->
Expand Down
69 changes: 63 additions & 6 deletions Data/HashMap/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ module Data.HashMap.Base

-- ** Lists
, toList
, fromList
, fromListWith

-- Internals used by the strict version
, Bitmap
, Hash
, Shift
, bitmapIndexedOrFull
, collision
, hash
Expand All @@ -68,7 +68,6 @@ module Data.HashMap.Base
, update16'
, update16With
, updateOrConcatWith
, updateOrSnocWith
) where

import Control.Applicative ((<$>), Applicative(pure))
Expand All @@ -79,13 +78,14 @@ import qualified Data.Foldable as Foldable
import qualified Data.List as L
import Data.Monoid (Monoid(mempty, mappend))
import Data.Traversable (Traversable(..))
import Data.Word (Word)
import Prelude hiding (filter, foldr, lookup, map, null, pred)

import qualified Data.HashMap.Array as A
import qualified Data.Hashable as H
import Data.Hashable (Hashable)
import Data.HashMap.Bits
import Data.HashMap.PopCount (popCount)
import Data.HashMap.UnsafeShift (unsafeShiftL)
import Data.HashMap.UnsafeShift (unsafeShiftL, unsafeShiftR)
import Data.Typeable (Typeable)

#if defined(__GLASGOW_HASKELL__)
Expand All @@ -94,6 +94,15 @@ import GHC.Exts ((==#), build, reallyUnsafePtrEquality#)

------------------------------------------------------------------------

-- | Convenience function. Compute a hash value for the given value.
hash :: H.Hashable a => a -> Hash
hash = fromIntegral . H.hash

data Leaf k v = L !k v

instance (NFData k, NFData v) => NFData (Leaf k v) where
rnf (L k v) = rnf k `seq` rnf v

-- Invariant: The length of the 1st argument to 'Full' is
-- 2^bitsPerSubkey

Expand Down Expand Up @@ -126,6 +135,10 @@ instance (Eq k, Hashable k) => Monoid (HashMap k v) where
mappend = union
{-# INLINE mappend #-}

type Hash = Word
type Bitmap = Word
type Shift = Int

instance (Show k, Show v) => Show (HashMap k v) where
show m = "fromList " ++ show (toList m)

Expand Down Expand Up @@ -735,6 +748,22 @@ toList = foldrWithKey (\ k v xs -> (k, v) : xs) []
#endif
{-# INLINE toList #-}

-- | /O(n)/ Construct a map with the supplied mappings. If the list
-- contains duplicate mappings, the later mappings take precedence.
fromList :: (Eq k, Hashable k) => [(k, v)] -> HashMap k v
fromList = L.foldl' (\ m (k, v) -> insert k v m) empty
#if __GLASGOW_HASKELL__ >= 700
{-# INLINABLE fromList #-}
#endif

-- | /O(n*log n)/ Construct a map from a list of elements. Uses
-- the provided function to merge duplicate entries.
fromListWith :: (Eq k, Hashable k) => (v -> v -> v) -> [(k, v)] -> HashMap k v
fromListWith f = L.foldl' (\ m (k, v) -> insertWith f k v m) empty
#if __GLASGOW_HASKELL__ >= 700
{-# INLINE fromListWith #-}
#endif

------------------------------------------------------------------------
-- Array operations

Expand Down Expand Up @@ -877,7 +906,35 @@ clone16 ary =
#endif

------------------------------------------------------------------------
-- Unsafe things
-- Bit twiddling

bitsPerSubkey :: Int
bitsPerSubkey = 4

maxChildren :: Int
maxChildren = fromIntegral $ 1 `unsafeShiftL` bitsPerSubkey

subkeyMask :: Bitmap
subkeyMask = 1 `unsafeShiftL` bitsPerSubkey - 1

sparseIndex :: Bitmap -> Bitmap -> Int
sparseIndex b m = popCount (b .&. (m - 1))

mask :: Word -> Shift -> Bitmap
mask w s = 1 `unsafeShiftL` index w s
{-# INLINE mask #-}

-- | Mask out the 'bitsPerSubkey' bits used for indexing at this level
-- of the tree.
index :: Hash -> Shift -> Int
index w s = fromIntegral $ (unsafeShiftR w s) .&. subkeyMask
{-# INLINE index #-}

-- | A bitmask with the 'bitsPerSubkey' least significant bits set.
fullNodeMask :: Bitmap
fullNodeMask = complement (complement 0 `unsafeShiftL`
fromIntegral (1 `unsafeShiftL` bitsPerSubkey))
{-# INLINE fullNodeMask #-}

-- | Check if two the two arguments are the same value. N.B. This
-- function might give false negatives (due to GC moving objects.)
Expand Down
67 changes: 0 additions & 67 deletions Data/HashMap/Bits.hs

This file was deleted.

30 changes: 3 additions & 27 deletions Data/HashMap/Lazy.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{-# LANGUAGE BangPatterns, CPP #-}
{-# LANGUAGE CPP #-}

#if __GLASGOW_HASKELL__ >= 702
{-# LANGUAGE Trustworthy #-}
Expand Down Expand Up @@ -34,7 +34,7 @@ module Data.HashMap.Lazy
HashMap

-- * Construction
, HM.empty
, empty
, singleton

-- * Basic interface
Expand All @@ -43,7 +43,7 @@ module Data.HashMap.Lazy
, HM.lookup
, lookupDefault
, insert
, HM.insertWith
, insertWith
, delete
, adjust

Expand Down Expand Up @@ -80,28 +80,4 @@ module Data.HashMap.Lazy
, fromListWith
) where

import Control.Monad.ST (runST)
import Data.Hashable (Hashable)

import Data.HashMap.Base as HM
import Data.HashMap.Mutable as M

-- | /O(n)/ Construct a map with the supplied mappings. If the list
-- contains duplicate mappings, the later mappings take precedence.
fromList :: (Eq k, Hashable k) => [(k, v)] -> HashMap k v
fromList = fromListWith const
#if __GLASGOW_HASKELL__ >= 700
{-# INLINABLE fromList #-}
#endif

-- | /O(n*log n)/ Construct a map from a list of elements. Uses
-- the provided function to merge duplicate entries.
fromListWith :: (Eq k, Hashable k) => (v -> v -> v) -> [(k, v)] -> HashMap k v
fromListWith f kvs0 = runST (go kvs0 M.empty >>= M.unsafeFreeze)
where
go [] !m = return m
go ((k, v):kvs) m = do m' <- M.insertWith f k v m
go kvs m'
#if __GLASGOW_HASKELL__ >= 700
{-# INLINE fromListWith #-}
#endif
Loading

0 comments on commit 5bdb93a

Please sign in to comment.