{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
module Treap.Rand
(
RTreap (..)
, emptyWithGen
, oneWithGen
, empty
, one
, size
, at
, query
, splitAt
, merge
, take
, drop
, rotate
, insert
, delete
, withTreap
, overTreap
, prettyPrint
) where
import Prelude hiding (drop, lookup, splitAt, take)
import Control.DeepSeq (NFData (..))
import Data.Coerce (Coercible)
import Data.Foldable (foldl')
import GHC.Exts (IsList (..))
import GHC.Generics (Generic)
import Treap.Measured (Measured (..))
import Treap.Pure (Priority (..), Size (..), Treap)
import qualified System.Random.Mersenne.Pure64 as Random
import qualified Treap.Pretty as Treap
import qualified Treap.Pure as Treap
data RTreap m a = RTreap
{ rTreapGen :: !Random.PureMT
, rTreapTree :: !(Treap m a)
} deriving (Show, Generic, Foldable)
instance (Eq m, Eq a) => Eq (RTreap m a) where
(==) :: RTreap m a -> RTreap m a -> Bool
RTreap _ t1 == RTreap _ t2 = t1 == t2
instance Monoid m => Measured m (RTreap m a) where
measure :: RTreap m a -> m
measure = withTreap measure
{-# INLINE measure #-}
instance Measured m a => IsList (RTreap m a) where
type Item (RTreap m a) = a
fromList :: [a] -> RTreap m a
fromList = foldl' (\t (i, a) -> insert i a t) empty . zip [0..]
{-# INLINE fromList #-}
toList :: RTreap m a -> [a]
toList = map snd . toList . rTreapTree
{-# INLINE toList #-}
instance (NFData m, NFData a) => NFData (RTreap m a) where
rnf RTreap{..} = rnf rTreapTree `seq` ()
defaultRandomGenerator :: Random.PureMT
defaultRandomGenerator = Random.pureMT 0
emptyWithGen :: Random.PureMT -> RTreap m a
emptyWithGen gen = RTreap gen Treap.Empty
{-# INLINE emptyWithGen #-}
empty :: RTreap m a
empty = emptyWithGen defaultRandomGenerator
{-# INLINE empty #-}
oneWithGen :: Measured m a => Random.PureMT -> a -> RTreap m a
oneWithGen gen a =
let (priority, newGen) = Random.randomWord64 gen
in RTreap newGen $ Treap.one (Priority priority) a
{-# INLINE oneWithGen #-}
one :: Measured m a => a -> RTreap m a
one = oneWithGen defaultRandomGenerator
{-# INLINE one #-}
size :: RTreap m a -> Int
size = unSize . withTreap Treap.size
{-# INLINE size #-}
at :: Int -> RTreap m a -> Maybe a
at i = withTreap $ Treap.at i
{-# INLINE at #-}
query :: forall m a . Measured m a => Int -> Int -> RTreap m a -> m
query l r = withTreap (Treap.query l r)
{-# INLINE query #-}
splitAt :: forall m a . Measured m a => Int -> RTreap m a -> (RTreap m a, RTreap m a)
splitAt i (RTreap gen t) = let (l, r) = Treap.splitAt i t in (RTreap gen l, RTreap gen r)
{-# INLINE splitAt #-}
merge :: Measured m a => RTreap m a -> RTreap m a -> RTreap m a
merge (RTreap gen t1) (RTreap _ t2) = RTreap gen (Treap.merge t1 t2)
{-# INLINE merge #-}
take :: forall m a . Measured m a => Int -> RTreap m a -> RTreap m a
take n = overTreap (Treap.take n)
{-# INLINE take #-}
drop :: forall m a . Measured m a => Int -> RTreap m a -> RTreap m a
drop n = overTreap (Treap.drop n)
{-# INLINE drop #-}
rotate :: forall m a . Measured m a => Int -> RTreap m a -> RTreap m a
rotate n = overTreap (Treap.rotate n)
{-# INLINE rotate #-}
insert :: forall m a . Measured m a => Int -> a -> RTreap m a -> RTreap m a
insert i a (RTreap gen t) =
let (priority, newGen) = Random.randomWord64 gen
in RTreap newGen $ Treap.insert i (Priority priority) a t
{-# INLINE insert #-}
delete :: forall m a . Measured m a => Int -> RTreap m a -> RTreap m a
delete i (RTreap gen t) = RTreap gen $ Treap.delete i t
{-# INLINE delete #-}
withTreap :: (Treap m a -> r) -> (RTreap m a -> r)
withTreap f = f . rTreapTree
{-# INLINE withTreap #-}
overTreap :: (Treap m a -> Treap m a) -> (RTreap m a -> RTreap m a)
overTreap set t = t { rTreapTree = set $ rTreapTree t }
{-# INLINE overTreap #-}
prettyPrint :: forall m a . (Coercible m a, Show a) => RTreap m a -> IO ()
prettyPrint = withTreap Treap.prettyPrint