-{-# OPTIONS -cpp #-}
+{-# OPTIONS -cpp -fglasgow-exts #-}
-----------------------------------------------------------------------------
-- |
-- Module : Data.Sequence
--
-- * Ralf Hinze and Ross Paterson,
-- \"Finger trees: a simple general-purpose data structure\",
--- submitted to /Journal of Functional Programming/.
+-- to appear in /Journal of Functional Programming/.
-- <http://www.soi.city.ac.uk/~ross/papers/FingerTree.html>
--
-- /Note/: Many of these operations have the same names as similar
reverse)
import qualified Prelude (foldr)
import qualified Data.List (foldl', intersperse)
+import Control.Monad (MonadPlus(..))
import Data.FunctorM
import Data.Typeable
+#ifdef __GLASGOW_HASKELL__
+import GHC.Exts (build)
+import Text.ParserCombinators.ReadP (char, skipSpaces, between, sepBy, (+++))
+import Text.Read (readPrec, readPrec_to_P, readP_to_Prec, minPrec)
+import Control.Monad (liftM)
+import Data.Generics.Basics (Data(..), Fixity(..),
+ constrIndex, mkConstr, mkDataType)
+#else
+import Data.Char (isSpace)
+#endif
+
#if TESTING
import Control.Monad (liftM, liftM2, liftM3, liftM4)
import Test.QuickCheck
#endif
-#if __GLASGOW_HASKELL__
-import Data.Generics.Basics (Data(..), mkNorepType)
-#endif
-
infixr 5 `consTree`
infixl 5 `snocTree`
class Sized a where
size :: a -> Int
-------------------------------------------------------------------------
--- Random access sequences
-------------------------------------------------------------------------
-
-- | General-purpose finite sequences.
newtype Seq a = Seq (FingerTree (Elem a))
instance Functor Seq where
fmap f (Seq xs) = Seq (fmap (fmap f) xs)
+instance Monad Seq where
+ return = singleton
+ xs >>= f = foldl' add empty xs
+ where add ys x = ys >< f x
+
+instance MonadPlus Seq where
+ mzero = empty
+ mplus = (><)
+
+instance FunctorM Seq where
+ fmapM f = foldlM f' empty
+ where f' ys x = do
+ y <- f x
+ return $! (ys |> y)
+ fmapM_ f = foldlM f' ()
+ where f' _ x = f x >> return ()
+
instance Eq a => Eq (Seq a) where
xs == ys = length xs == length ys && toList xs == toList ys
compare xs ys = compare (toList xs) (toList ys)
#if TESTING
-instance (Show a) => Show (Seq a) where
+instance Show a => Show (Seq a) where
showsPrec p (Seq x) = showsPrec p x
#else
instance Show a => Show (Seq a) where
showChar '>'
#endif
-instance FunctorM Seq where
- fmapM f = foldlM f' empty
- where f' ys x = do
- y <- f x
- return $! (ys |> y)
- fmapM_ f = foldlM f' ()
- where f' _ x = f x >> return ()
+instance Read a => Read (Seq a) where
+ -- avoid lex, as < or > might be followed by symbol characters.
+#ifdef __GLASGOW_HASKELL__
+ readPrec = readP_to_Prec $ const $
+ parens $
+ between (litChar '<') (litChar '>') $
+ liftM fromList $
+ readPrec_to_P readPrec minPrec `sepBy` litChar ','
+ where parens p = p +++ between (litChar '(') (litChar ')') (parens p)
+ litChar c = skipSpaces >> char c
+#else
+ readsPrec _ = readParen False $ \ r ->
+ case dropWhile isSpace r of
+ ('<':s) -> case dropWhile isSpace s of
+ ('>':t) -> return (empty,t)
+ _ -> readRest empty s
+ _ -> []
+ where readRest xs s = do
+ (x,t) <- reads s
+ let xs' = xs |> x
+ case dropWhile isSpace t of
+ ('>':u) -> return (xs',u)
+ (',':u) -> readRest xs' u
+ _ -> []
+#endif
#include "Typeable.h"
INSTANCE_TYPEABLE1(Seq,seqTc,"Seq")
#if __GLASGOW_HASKELL__
instance Data a => Data (Seq a) where
- gfoldl f z xs = z fromList `f` toList xs
- toConstr _ = error "toConstr"
- gunfold _ _ = error "gunfold"
- dataTypeOf _ = mkNorepType "Data.Sequence.Seq"
+ gfoldl f z s = case viewl s of
+ EmptyL -> z empty
+ x :< xs -> z (<|) `f` x `f` xs
+
+ gunfold k z c = case constrIndex c of
+ 1 -> z empty
+ 2 -> k (k (z (<|)))
+ _ -> error "gunfold"
+
+ toConstr xs
+ | null xs = emptyConstr
+ | otherwise = consConstr
+
+ dataTypeOf _ = seqDataType
+
+ dataCast1 = gcast1
+
+emptyConstr = mkConstr seqDataType "empty" [] Prefix
+consConstr = mkConstr seqDataType "<|" [] Infix
+seqDataType = mkDataType "Data.Sequence.Seq" [emptyConstr, consConstr]
#endif
-- Finger trees
#endif
instance Sized a => Sized (FingerTree a) where
+ {-# SPECIALIZE instance Sized (FingerTree (Elem a)) #-}
+ {-# SPECIALIZE instance Sized (FingerTree (Node a)) #-}
size Empty = 0
size (Single x) = size x
size (Deep v _ _ _) = v
Deep v (fmap f pr) (fmap (fmap f) m) (fmap f sf)
{-# INLINE deep #-}
+{-# SPECIALIZE deep :: Digit (Elem a) -> FingerTree (Node (Elem a)) -> Digit (Elem a) -> FingerTree (Elem a) #-}
+{-# SPECIALIZE deep :: Digit (Node a) -> FingerTree (Node (Node a)) -> Digit (Node a) -> FingerTree (Node a) #-}
deep :: Sized a => Digit a -> FingerTree (Node a) -> Digit a -> FingerTree a
deep pr m sf = Deep (size pr + size m + size sf) pr m sf
fmap f (Four a b c d) = Four (f a) (f b) (f c) (f d)
instance Sized a => Sized (Digit a) where
+ {-# SPECIALIZE instance Sized (Digit (Elem a)) #-}
+ {-# SPECIALIZE instance Sized (Digit (Node a)) #-}
size xs = foldlDigit (\ i x -> i + size x) 0 xs
{-# SPECIALIZE digitToTree :: Digit (Elem a) -> FingerTree (Elem a) #-}
size (Node3 v _ _ _) = v
{-# INLINE node2 #-}
+{-# SPECIALIZE node2 :: Elem a -> Elem a -> Node (Elem a) #-}
+{-# SPECIALIZE node2 :: Node a -> Node a -> Node (Node a) #-}
node2 :: Sized a => a -> a -> Node a
node2 a b = Node2 (size a + size b) a b
{-# INLINE node3 #-}
+{-# SPECIALIZE node3 :: Elem a -> Elem a -> Elem a -> Node (Elem a) #-}
+{-# SPECIALIZE node3 :: Node a -> Node a -> Node a -> Node (Node a) #-}
node3 :: Sized a => a -> a -> a -> Node a
node3 a b c = Node3 (size a + size b + size c) a b c
-- | /O(n)/. List of elements of the sequence.
toList :: Seq a -> [a]
+#ifdef __GLASGOW_HASKELL__
+{-# INLINE toList #-}
+toList xs = build (\ c n -> foldr c n xs)
+#else
toList = foldr (:) []
+#endif
------------------------------------------------------------------------
-- Folds