module Data.Queue.Indexed.Splay
(Splay(..))
where
import Data.Queue.Indexed.Class
import GHC.TypeLits
import Control.DeepSeq (NFData(rnf))
data Splay n a where
Leaf :: Splay 0 a
Node :: a -> !(Splay n a) -> !(Splay m a) -> Splay (1 + n + m) a
instance Ord a => IndexedQueue Splay a where
minView (Node xx aa bb) = minv aa xx bb where
minv :: Splay n a -> a -> Splay m a -> (a, Splay (n+m) a)
minv Leaf x b = (x, b)
minv (Node x Leaf b) y c = (x, Node y b c)
minv (Node y (Node a x b) c) z d = (w, Node y ab (Node z c d))
where
(w,ab) = minv x a b
empty = Leaf
insert x xs = case partitionLeGt x xs of
SumsTo a b -> Node x a b
minViewMay Leaf b _ = b
minViewMay n@Node {} _ f = uncurry f (minView n)
instance Ord a => MeldableIndexedQueue Splay a where
merge Leaf ys = ys
merge xs Leaf = xs
merge (Node x a b) ys = case partitionLeGt x ys of
SumsTo c d -> Node x (merge c a) (merge d b)
instance NFData a =>
NFData (Splay n a) where
rnf Leaf = ()
rnf (Node x l r) = rnf x `seq` rnf l `seq` rnf r
data SumsTo n a where
SumsTo :: !(Splay x a) -> !(Splay y a) -> SumsTo (x + y) a
partitionLeGt :: Ord a => a -> Splay n a -> SumsTo n a
partitionLeGt _ Leaf = SumsTo Leaf Leaf
partitionLeGt k t@(Node x a b) =
if x > k
then case a of
Leaf -> SumsTo Leaf t
Node y aa ab ->
if y > k
then case partitionLeGt k aa of
SumsTo small big ->
SumsTo small (Node y big (Node x ab b))
else case partitionLeGt k ab of
SumsTo small big ->
SumsTo (Node y aa small) (Node x big b)
else case b of
Leaf -> SumsTo t Leaf
Node y ba bb ->
if y > k
then case partitionLeGt k ba of
SumsTo small big ->
SumsTo (Node x a small) (Node y big bb)
else case partitionLeGt k bb of
SumsTo small big ->
SumsTo (Node y (Node x a ba) small) big