packages feed

IntervalMap-0.4.1.1: bench/IvMapSortedList.hs

module IvMapSortedList (IVS, size, empty, singleton, insert, insertWithKey, lookup, containing, fromList) where

import Prelude hiding (lookup)
import Data.IntervalMap.Generic.Interval
import Control.DeepSeq
import Data.List (sortBy)


data Entry k v = E !k !v deriving (Eq, Ord, Show)

instance (NFData k, NFData v) => NFData (Entry k v) where
  rnf (E k v) = k `deepseq` v `deepseq` ()

newtype IVS k v = IVS [Entry k v] deriving (Eq, Ord, Show)

instance (NFData k, NFData v) => NFData (IVS k v) where
  rnf (IVS v) = v `deepseq` ()

size :: IVS k v -> Int
size (IVS es) = length es

empty :: IVS k v
empty = IVS []

singleton :: k -> v -> IVS k v
singleton k v = IVS [E k v]

insert :: Ord k => k -> v -> IVS k v -> IVS k v
insert =  insertWithKey (\_ val _ -> val)

insertWithKey :: Ord k => (k -> v -> v -> v) -> k -> v -> IVS k v -> IVS k v
insertWithKey f key val (IVS m) = IVS (go m)
  where
    go [] = [E key val] 
    go es@(e@(E k v) : es') = case compare key k of
                                GT -> e : go es'
                                LT -> E key val : es
                                EQ -> E key (f key val v) : es'

lookup :: Ord k => k -> IVS k v -> Maybe v
lookup key (IVS m) = key `seq` go m
  where
    go (E k v : es) = case compare key k of
                        GT -> go es
                        EQ -> Just v
                        LT -> Nothing
    go [] = Nothing


containing :: (Interval k e) => IVS k v -> e -> [(k, v)]
(IVS m) `containing` p = p `seq` go m
  where
    go (E k v : es) | p `above` k = go es
                    | p `below` k = []
                    | otherwise   = (k,v) : go es
    go [] = []

fromList :: Ord k => [(k, v)] -> IVS k v
fromList =  foldr (\(k,v) m -> insert k v m) empty . sortBy cmpKey
  where cmpKey (k1,_) (k2,_) = compare k1 k2