packages feed

sequence-0.9.9.0: Data/Sequence/BSeq/Internal.hs

{-# LANGUAGE CPP #-}
{-# LANGUAGE Rank2Types,GADTs, DataKinds, TypeOperators #-}
{-# LANGUAGE DeriveTraversable #-}
#if __GLASGOW_HASKELL__ < 710
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
#endif



-----------------------------------------------------------------------------
-- |
-- Module      :  Data.Sequence.BSeq
-- Copyright   :  (c) Atze van der Ploeg 2014
-- License     :  BSD-style
-- Maintainer  :  atzeus@gmail.org
-- Stability   :  provisional
-- Portability :  portable
--
-- A catenable qeueue, implemented as a binary tree,
-- with good amortized performance when used ephemerally.
--
--
-----------------------------------------------------------------------------
module Data.Sequence.BSeq.Internal (BSeq (..))  where
import Control.Applicative hiding (empty)
import Data.Foldable
import Data.Monoid (Monoid (..), (<>))
import Data.Traversable
import qualified Text.Read as TR
#if MIN_VERSION_base(4,9,0)
import qualified Data.Semigroup as Semigroup
import Data.Functor.Classes (Show1 (..))
#endif
import Data.Function (on)
import Prelude hiding (foldr,foldl)
import Data.SequenceClass

-- | A catenable queue intended for ephemeral use.
data BSeq a = Empty | Leaf a | Node (BSeq a) (BSeq a)
-- Invariant: Neither child of a Node may be Empty.
  deriving (Functor, Traversable)

instance Foldable BSeq where
  foldMap _ Empty = mempty
  foldMap f (Leaf a) = f a
  foldMap f (Node l r) = foldMap f l `mappend` foldMap f r

  foldr _ n Empty = n
  foldr c n (Leaf a) = c a n
  foldr c n (Node l r) = foldr c (foldr c n r) l

#if MIN_VERSION_base(4,8,0)
  -- This implementation avoids digging into Nodes to see
  -- that they're not empty.
  null Empty = True
  null _ = False
#endif

#if MIN_VERSION_base(4,9,0)
instance Semigroup.Semigroup (BSeq a) where
  (<>) = (><)
#endif
instance Monoid (BSeq a) where
  mempty = empty
#if MIN_VERSION_base(4,9,0)
  mappend = (Semigroup.<>)
#else
  mappend = (><)
#endif

instance Show a => Show (BSeq a) where
    showsPrec p xs = showParen (p > 10) $
        showString "fromList " . shows (toList xs)

#if MIN_VERSION_base(4,9,0)
instance Show1 BSeq where
  liftShowsPrec _shwsPrc shwList p xs = showParen (p > 10) $
        showString "fromList " . shwList (toList xs)
#endif

instance Read a => Read (BSeq a) where
    readPrec = TR.parens $ TR.prec 10 $ do
        TR.Ident "fromList" <- TR.lexP
        xs <- TR.readPrec
        return (fromList xs)

    readListPrec = TR.readListPrecDefault

instance Eq a => Eq (BSeq a) where
  (==) = (==) `on` toList

instance Ord a => Ord (BSeq a) where
  compare = compare `on` toList

instance Sequence BSeq where
  empty     = Empty
  singleton = Leaf
  Empty      >< r = r
  l          >< Empty = l
  Node l r   >< z = Node l (Node r z)
  l@(Leaf _) >< z = Node l z
  viewl Empty         = EmptyL
  viewl (Leaf x)      = x :< Empty
  viewl (Node l r)    = case viewl l of
    EmptyL -> error "Invariant failure"
    x :< l' -> (x :<) $! l' >< r
  viewr Empty = EmptyR
  viewr (Leaf x) = Empty :> x
  viewr (Node l r) = case viewr r of
    EmptyR -> error "Invariant failure"
    r' :> x -> (:> x) $! l >< r'
  fromList [] = Empty
  fromList [x] = Leaf x
  fromList (x : xs) = Node (Leaf x) (fromList xs)