module Data.Raz.Sequence.Internal where
import Control.Applicative
import qualified Control.Monad as Monad
import Control.Monad.Random hiding (fromList)
import Data.Foldable (toList)
import qualified Data.List as List
import Data.Tuple (swap)
import System.IO.Unsafe
import Prelude hiding (lookup, zipWith)
import qualified Data.Raz.Core.Internal as Raz
import qualified Data.Raz.Core.Sequence as Raz
import Data.Raz.Util
data Seq' g a = Seq' !g !(Raz.Tree a)
deriving (Functor, Foldable, Traversable)
instance Eq a => Eq (Seq' g a) where
Seq' _ t == Seq' _ t' = t == t'
instance Ord a => Ord (Seq' g a) where
compare (Seq' _ t) (Seq' _ t') = compare t t'
instance Show a => Show (Seq' g a) where
showsPrec d (Seq' _ t) = showsPrec d t
instance Applicative (Seq' StdGen) where
pure a = createSeq (Raz.Leaf a)
(<*>) = seqLift2 Raz.ap
type Seq = Seq' StdGen
type Impure a = a
type Splittable g = RandomGen g
empty :: Seq a
empty = empty' (unsafePerformIO newStdGen)
singleton :: a -> Seq a
singleton a = singleton' (unsafePerformIO newStdGen) a
fromList :: [a] -> Seq a
fromList as = fromList' (unsafePerformIO newStdGen) as
fromFunction :: Int -> (Int -> a) -> Seq a
fromFunction n f = fromList (fmap f [0 .. n 1])
(<|) :: RandomGen g => a -> Seq' g a -> Seq' g a
a <| as = seqBind as (Raz.cons a)
(|>) :: RandomGen g => Seq' g a -> a -> Seq' g a
as |> a = seqBind as (`Raz.snoc` a)
(><) :: RandomGen g => Seq' g a -> Seq' g a -> Seq' g a
s1 >< Seq' _ t2 = seqBind s1 (\t1 -> Raz.append t1 t2)
empty' :: g -> Seq' g a
empty' g = Seq' g Raz.Empty
singleton' :: g -> a -> Seq' g a
singleton' g = Seq' g . Raz.Leaf
fromList' :: RandomGen g => g -> [a] -> Seq' g a
fromList' g as = seqRun g (Raz.fromList as)
replicate :: Int -> a -> Seq a
replicate n a = fromList $ List.replicate n a
replicateA :: Applicative f => Int -> f a -> f (Seq a)
replicateA n a = fromList <$> Monad.replicateM n a
replicateM :: Monad m => Int -> m a -> m (Seq a)
replicateM n = unwrapMonad . replicateA n . WrapMonad
cycleTaking :: RandomGen g => Int -> Seq' g a -> Seq' g a
cycleTaking k (Seq' g t) = fromList' g . List.take k . cycle . toList $ t
iterateN :: Int -> (a -> a) -> a -> Seq a
iterateN n f = fromList . List.take n . List.iterate f
unfoldr :: (b -> Maybe (a, b)) -> b -> Seq a
unfoldr f = fromList . List.unfoldr f
unfoldl :: (b -> Maybe (b, a)) -> b -> Seq a
unfoldl f = fromList . reverse . List.unfoldr (fmap swap . f)
null :: Seq' g a -> Bool
null (Seq' _ Raz.Empty) = True
null _ = False
length :: Seq' g a -> Int
length (Seq' _ t) = Raz.size t
data ViewL' g a
= EmptyL
| a :< Seq' g a
viewl :: Seq' g a -> ViewL' g a
viewl (Seq' _ Raz.Empty) = EmptyL
viewl (Seq' g t) = Raz.viewC raz :< Seq' g t'
where
raz = Raz.focusL t
t' = Raz.unfocus . Raz.removeC Raz.R $ raz
tails :: RandomGen g => Seq' g a -> Seq' g (Seq' g a)
tails s = seqBind s (Raz.tailsWith splitting)
where
splitting a = getSplit <&> \g -> Seq' g a
takeWhileL :: (a -> Bool) -> Seq' g a -> Seq' g a
takeWhileL = seqLift . Raz.takeWhileL
takeWhileR :: (a -> Bool) -> Seq' g a -> Seq' g a
takeWhileR = seqLift . Raz.takeWhileR
dropWhileL :: (a -> Bool) -> Seq' g a -> Seq' g a
dropWhileL = seqLift . Raz.dropWhileL
dropWhileR :: (a -> Bool) -> Seq' g a -> Seq' g a
dropWhileR = seqLift . Raz.dropWhileR
spanl :: RandomGen g => (a -> Bool) -> Seq' g a -> (Seq' g a, Seq' g a)
spanl = seqLiftSplit . Raz.spanL
spanr :: RandomGen g => (a -> Bool) -> Seq' g a -> (Seq' g a, Seq' g a)
spanr = seqLiftSplit . Raz.spanR
breakl :: RandomGen g => (a -> Bool) -> Seq' g a -> (Seq' g a, Seq' g a)
breakl = seqLiftSplit . Raz.breakL
breakr :: RandomGen g => (a -> Bool) -> Seq' g a -> (Seq' g a, Seq' g a)
breakr = seqLiftSplit . Raz.breakR
partition :: RandomGen g => (a -> Bool) -> Seq' g a -> (Seq' g a, Seq' g a)
partition = seqLiftSplit . Raz.partition
filter :: (a -> Bool) -> Seq' g a -> Seq' g a
filter = seqLift . Raz.filter
lookup :: Int -> Seq' g a -> Maybe a
lookup = seqApply . Raz.lookup
(?!) :: Seq' g a -> Int -> Maybe a
(?!) = flip lookup
index :: Seq' g a -> Int -> a
index s n = seqApply (\t -> Raz.index t n) s
adjust :: (a -> a) -> Int -> Seq' g a -> Seq' g a
adjust f = seqLift . Raz.adjust f
adjust' :: (a -> a) -> Int -> Seq' g a -> Seq' g a
adjust' f = seqLift . Raz.adjust' f
update :: Int -> a -> Seq' g a -> Seq' g a
update n = seqLift . Raz.update n
take :: Int -> Seq' g a -> Seq' g a
take = seqLift . Raz.take
drop :: Int -> Seq' g a -> Seq' g a
drop = seqLift . Raz.drop
insertAt :: RandomGen g => Int -> a -> Seq' g a -> Seq' g a
insertAt n = seqDnib . Raz.insertAt n
deleteAt :: Int -> Seq' g a -> Seq' g a
deleteAt = seqLift . Raz.deleteAt
splitAt :: RandomGen g => Int -> Seq' g a -> (Seq' g a, Seq' g a)
splitAt = seqLiftSplit . Raz.splitAt
mapWithIndex :: (Int -> a -> b) -> Seq' g a -> Seq' g b
mapWithIndex = seqLift . Raz.mapWithIndex
traverseWithIndex
:: Applicative f => (Int -> a -> f b) -> Seq' g a -> f (Seq' g b)
traverseWithIndex = seqLens . Raz.traverseWithIndex
zip :: Seq' g a -> Seq' g b -> Seq' g (a, b)
zip = zipWith (,)
zipWith :: (a -> b -> c) -> Seq' g a -> Seq' g b -> Seq' g c
zipWith = seqLift2 . Raz.zipWith
splitSeq :: Splittable g => Seq' g a -> (Seq' g a, Seq' g a)
splitSeq (Seq' g t) = (Seq' g1 t, Seq' g2 t)
where
(g1, g2) = split g
refreshSeq :: Seq' g a -> Impure (Seq a)
refreshSeq (Seq' _ t) = createSeq t
createSeq :: Raz.Tree a -> Impure (Seq a)
createSeq t = Seq' (unsafePerformIO newStdGen) t
seqBind :: Seq' g a -> (Raz.Tree a -> Rand g (Raz.Tree b)) -> Seq' g b
seqBind (Seq' g t) f = Seq' g' t'
where
(t', g') = runRand (f t) g
seqDnib :: (Raz.Tree a -> Rand g (Raz.Tree b)) -> Seq' g a -> Seq' g b
seqDnib = flip seqBind
seqRun :: g -> Rand g (Raz.Tree a) -> Seq' g a
seqRun g t = Seq' g' t'
where
(t', g') = runRand t g
seqLift :: (Raz.Tree a -> Raz.Tree b) -> Seq' g a -> Seq' g b
seqLift f (Seq' g t) = Seq' g (f t)
seqLift2
:: (Raz.Tree a -> Raz.Tree b -> Raz.Tree c)
-> Seq' g a -> Seq' g b -> Seq' g c
seqLift2 f (Seq' g ta) (Seq' _ tb) = Seq' g (f ta tb)
seqLiftSplit
:: Splittable g
=> (Raz.Tree a -> (Raz.Tree b, Raz.Tree c))
-> Seq' g a -> (Seq' g b, Seq' g c)
seqLiftSplit f (Seq' g t) = (Seq' g1 t1, Seq' g2 t2)
where
(g1, g2) = split g
(t1, t2) = f t
seqApply :: (Raz.Tree a -> b) -> Seq' g a -> b
seqApply f (Seq' _ t) = f t
seqLens
:: Functor f
=> (Raz.Tree a -> f (Raz.Tree b))
-> Seq' g a -> f (Seq' g b)
seqLens f (Seq' g a) = Seq' g <$> f a