{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE MultiParamTypeClasses #-}
#if __GLASGOW_HASKELL__ >= 710
{-# LANGUAGE AutoDeriveTypeable #-}
#endif
module HaskellWorks.Data.IntervalMap.FingerTree
(
Interval(..)
, point
, IntervalMap(..)
, empty
, singleton
, insert
, union
, search
, intersections
, dominators
) where
import Control.Applicative ((<$>))
import Control.DeepSeq
import Data.Foldable (Foldable (foldMap))
import Data.Monoid
import Data.Traversable (Traversable (traverse))
import GHC.Generics
import HaskellWorks.Data.FingerTree (FingerTree, Measured (..), ViewL (..), (<|), (><), (|>))
import qualified Data.Semigroup as S
import qualified HaskellWorks.Data.FingerTree as FT
data Interval v = Interval { low :: v, high :: v }
deriving (Eq, Ord, Show, Generic, NFData)
point :: v -> Interval v
point v = Interval v v
data Node v a = Node (Interval v) a deriving (Generic, NFData)
instance Functor (Node v) where
fmap f (Node i x) = Node i (f x)
instance Foldable (Node v) where
foldMap f (Node _ x) = f x
instance Traversable (Node v) where
traverse f (Node i x) = Node i <$> f x
data IntInterval v = NoInterval | IntInterval (Interval v) v deriving (Generic, NFData)
appendInterval :: Ord v => IntInterval v -> IntInterval v -> IntInterval v
appendInterval (NoInterval ) (i ) = i
appendInterval (i ) (NoInterval ) = i
appendInterval (IntInterval _ hi1) (IntInterval int2 hi2) = IntInterval int2 (max hi1 hi2)
{-# INLINE appendInterval #-}
instance Ord v => S.Semigroup (IntInterval v) where
(<>) = appendInterval
{-# INLINE (<>) #-}
instance Ord v => Monoid (IntInterval v) where
mempty = NoInterval
{-# INLINE mempty #-}
mappend = appendInterval
{-# INLINE mappend #-}
instance (Ord v) => Measured (IntInterval v) (Node v a) where
measure (Node i _) = IntInterval i (high i)
newtype IntervalMap v a =
IntervalMap (FingerTree (IntInterval v) (Node v a))
deriving (Generic, NFData)
instance Functor (IntervalMap v) where
fmap f (IntervalMap t) = IntervalMap (FT.unsafeFmap (fmap f) t)
instance Foldable (IntervalMap v) where
foldMap f (IntervalMap t) = foldMap (foldMap f) t
instance Traversable (IntervalMap v) where
traverse f (IntervalMap t) = IntervalMap <$> FT.unsafeTraverse (traverse f) t
instance (Ord v) => S.Semigroup (IntervalMap v a) where
(<>) = union
{-# INLINE (<>) #-}
instance (Ord v) => Monoid (IntervalMap v a) where
mempty = empty
{-# INLINE mempty #-}
mappend = union
{-# INLINE mappend #-}
empty :: (Ord v) => IntervalMap v a
empty = IntervalMap FT.empty
singleton :: (Ord v) => Interval v -> a -> IntervalMap v a
singleton i x = IntervalMap (FT.singleton (Node i x))
insert :: (Ord v) => Interval v -> a -> IntervalMap v a -> IntervalMap v a
insert (Interval lo hi) _ m | lo > hi = m
insert i x (IntervalMap t) = IntervalMap (l >< Node i x <| r)
where (l, r) = FT.split larger t
larger (IntInterval k _) = k >= i
larger NoInterval = error "larger NoInterval"
union :: (Ord v) => IntervalMap v a -> IntervalMap v a -> IntervalMap v a
union (IntervalMap xs) (IntervalMap ys) = IntervalMap (merge1 xs ys)
where merge1 as bs = case FT.viewl as of
EmptyL -> bs
a@(Node i _) :< as' -> l >< a <| merge2 as' r
where (l, r) = FT.split larger bs
larger (IntInterval k _) = k >= i
larger NoInterval = error "larger NoInterval"
merge2 as bs = case FT.viewl bs of
EmptyL -> as
b@(Node i _) :< bs' -> l >< b <| merge1 r bs'
where (l, r) = FT.split larger as
larger (IntInterval k _) = k > i
larger NoInterval = error "larger NoInterval"
intersections :: (Ord v) => Interval v -> IntervalMap v a -> [(Interval v, a)]
intersections i = inRange (low i) (high i)
dominators :: (Ord v) => Interval v -> IntervalMap v a -> [(Interval v, a)]
dominators i = inRange (high i) (low i)
search :: (Ord v) => v -> IntervalMap v a -> [(Interval v, a)]
search p = inRange p p
inRange :: (Ord v) => v -> v -> IntervalMap v a -> [(Interval v, a)]
inRange lo hi (IntervalMap t) = matches (FT.takeUntil (greater hi) t)
where matches xs = case FT.viewl (FT.dropUntil (atleast lo) xs) of
EmptyL -> []
Node i x :< xs' -> (i, x) : matches xs'
atleast :: (Ord v) => v -> IntInterval v -> Bool
atleast k (IntInterval _ hi) = k <= hi
atleast _ NoInterval = error "atleast NoInterval"
greater :: (Ord v) => v -> IntInterval v -> Bool
greater k (IntInterval i _) = low i > k
greater _ NoInterval = error "greater NoInterval"