packages feed

fast-builder-0.0.0.0: benchmarks/aeson/HashMapExts.hs

{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
module HashMapExts where

import qualified Data.HashMap.Strict as H
import Data.Monoid
import GHC.Exts (Array#, sizeofArray#, indexArray#, Int(..))
import Unsafe.TrueName (quasiName)

import HashMapNames

foldMapWithKey :: (Monoid m) => (k -> a -> m) -> H.HashMap k a -> m
foldMapWithKey f = go
  where
    go hm = case hm of
      [quasiName|Empty ''H.HashMap|] -> mempty
      [quasiName|BitmapIndexed ''H.HashMap _ ary|] -> foldMapArray go ary
      [quasiName|Full ''H.HashMap ary|] -> foldMapArray go ary
      [quasiName|Collision ''H.HashMap _ ary|] -> foldMapArray leaf ary
      [quasiName|Leaf ''H.HashMap _ l|] -> leaf l

    leaf $(lPat "k" "v")  = f k v
{-# INLINE foldMapWithKey #-}

foldMapArray :: (Monoid m) => (a -> m) -> $(arrayType) a -> m
foldMapArray f $(arrayPat "arr") = foldMapArray' f arr

foldMapArray' :: (Monoid m) => (a -> m) -> Array# a -> m
foldMapArray' f arr = go 0
  where
    go k@(I# k#)
      | k >= I# (sizeofArray# arr) = mempty
      | otherwise = case indexArray# arr k# of
        (# v #) -> f v <> go (k + 1)
{-# INLINE foldMapArray' #-}