rope 0.1 → 0.2
raw patch · 11 files changed
+279/−690 lines, 11 filesdep −mtlPVP ok
version bump matches the API change (PVP)
Dependencies removed: mtl
API changes (from Hackage documentation)
- Data.Rope: class (Reducer ByteString a) => Annotation a
- Data.Rope: class Packable a
- Data.Rope: drop' :: (Annotation a) => Int -> Rope a -> a
- Data.Rope: elide :: (Annotation a) => Int -> Int -> Rope a -> Rope a
- Data.Rope: elide' :: (Annotation a) => Int -> Int -> Rope a -> a
- Data.Rope: pack :: (Packable a, Annotation m) => a -> Rope m
- Data.Rope: packl :: (Packable a, Annotation m) => a -> Rope m -> Rope m
- Data.Rope: packr :: (Packable a, Annotation m) => Rope m -> a -> Rope m
- Data.Rope: splitAt' :: (Annotation a) => Int -> Rope a -> (a, a)
- Data.Rope: take' :: (Annotation a) => Int -> Rope a -> a
- Data.Rope.Body: Count :: Int -> Count
- Data.Rope.Body: getCount :: Count -> Int
- Data.Rope.Body: instance Data Count
- Data.Rope.Body: instance Enum Count
- Data.Rope.Body: instance Eq Count
- Data.Rope.Body: instance Measured Count Chunk
- Data.Rope.Body: instance Monoid Count
- Data.Rope.Body: instance Num Count
- Data.Rope.Body: instance Ord Count
- Data.Rope.Body: instance Read Count
- Data.Rope.Body: instance Show Count
- Data.Rope.Body: instance Typeable Count
- Data.Rope.Body: newtype Count
- Data.Rope.Internal: break8 :: (Annotation m) => (Word8 -> Bool) -> Rope m -> (Rope m, Rope m)
- Data.Rope.Internal: class (Reducer ByteString a) => Annotation a
- Data.Rope.Internal: class Packable a
- Data.Rope.Internal: cons8 :: (Reducer ByteString m) => Word8 -> Rope m -> Rope m
- Data.Rope.Internal: data Rope a
- Data.Rope.Internal: drop' :: (Annotation a) => Int -> Rope a -> a
- Data.Rope.Internal: elide :: (Annotation a) => Int -> Int -> Rope a -> Rope a
- Data.Rope.Internal: elide' :: (Annotation a) => Int -> Int -> Rope a -> a
- Data.Rope.Internal: instance (Annotation a) => Annotation (Rope a)
- Data.Rope.Internal: instance (Annotation a, Annotation b) => Annotation (a :*: b)
- Data.Rope.Internal: instance (Annotation a, Annotation b) => Annotation (a, b)
- Data.Rope.Internal: instance (Annotation a, Data a) => Data (Rope a)
- Data.Rope.Internal: instance (Annotation n) => Packable (Rope n)
- Data.Rope.Internal: instance (Eq a) => Eq (Rope a)
- Data.Rope.Internal: instance (Monoid a) => Monoid (Rope a)
- Data.Rope.Internal: instance (Packable a, Annotation m) => Reducer a (Rope m)
- Data.Rope.Internal: instance (Show a) => Show (Rope a)
- Data.Rope.Internal: instance Annotation ()
- Data.Rope.Internal: instance Annotation Body
- Data.Rope.Internal: instance Annotation ByteString
- Data.Rope.Internal: instance Applicative Rope
- Data.Rope.Internal: instance Comonad Rope
- Data.Rope.Internal: instance Foldable Rope
- Data.Rope.Internal: instance Functor Rope
- Data.Rope.Internal: instance Measured Count (Rope a)
- Data.Rope.Internal: instance Monad Rope
- Data.Rope.Internal: instance MonadWriter (Rope ()) Rope
- Data.Rope.Internal: instance Packable ByteString
- Data.Rope.Internal: instance Packable Char
- Data.Rope.Internal: instance Packable Chunk
- Data.Rope.Internal: instance Packable String
- Data.Rope.Internal: instance Packable Word8
- Data.Rope.Internal: instance Packable [Word8]
- Data.Rope.Internal: instance Traversable Rope
- Data.Rope.Internal: instance Typeable1 Rope
- Data.Rope.Internal: packl :: (Packable a, Annotation m) => a -> Rope m -> Rope m
- Data.Rope.Internal: packr :: (Packable a, Annotation m) => Rope m -> a -> Rope m
- Data.Rope.Internal: splitAt' :: (Annotation a) => Int -> Rope a -> (a, a)
- Data.Rope.Internal: take' :: (Annotation a) => Int -> Rope a -> a
- Data.Rope.Internal: uncons8 :: (Annotation m) => Rope m -> Maybe (Word8, Rope m)
- Data.Rope.Internal: unsnoc8 :: (Annotation m) => Rope m -> Maybe (Rope m, Word8)
- Data.Rope.Unpackable: class Unpackable a
- Data.Rope.Unpackable: head :: (Unpackable a) => Rope m -> a
- Data.Rope.Unpackable: instance Monoid F
- Data.Rope.Unpackable: instance UTF8Bytes F Int
- Data.Rope.Unpackable: instance Unpackable ByteString
- Data.Rope.Unpackable: instance Unpackable Char
- Data.Rope.Unpackable: instance Unpackable Chunk
- Data.Rope.Unpackable: instance Unpackable Word8
- Data.Rope.Unpackable: last :: (Unpackable a) => Rope m -> a
- Data.Rope.Unpackable: uncons :: (Unpackable a, Annotation m) => Rope m -> Maybe (a, Rope m)
- Data.Rope.Unpackable: unpack :: (Unpackable a) => Rope m -> [a]
- Data.Rope.Unpackable: unsnoc :: (Unpackable a, Annotation m) => Rope m -> Maybe (Rope m, a)
- Data.Rope.Util.Bifunctor: bimap :: (Bifunctor f) => (a -> b) -> (c -> d) -> f a c -> f b d
- Data.Rope.Util.Bifunctor: class Bifunctor f
- Data.Rope.Util.Bifunctor: first :: (Bifunctor f) => (a -> b) -> f a c -> f b c
- Data.Rope.Util.Bifunctor: instance Bifunctor (,)
- Data.Rope.Util.Bifunctor: instance Bifunctor Either
- Data.Rope.Util.Bifunctor: second :: (Bifunctor f) => (b -> c) -> f a b -> f a c
- Data.Rope.Util.Comonad: class (Functor w) => Comonad w
- Data.Rope.Util.Comonad: duplicate :: (Comonad w) => w a -> w (w a)
- Data.Rope.Util.Comonad: extend :: (Comonad w) => (w a -> b) -> w a -> w b
- Data.Rope.Util.Comonad: extract :: (Comonad w) => w a -> a
- Data.Rope.Util.Coproduct: (|||) :: (Coproduct s) => (a -> c) -> (b -> c) -> s a b -> c
- Data.Rope.Util.Coproduct: Inl :: !a -> :+ a b
- Data.Rope.Util.Coproduct: Inr :: b -> :+ a b
- Data.Rope.Util.Coproduct: Left' :: !a -> :+: a b
- Data.Rope.Util.Coproduct: Right' :: !b -> :+: a b
- Data.Rope.Util.Coproduct: class (Bifunctor s) => Coproduct s
- Data.Rope.Util.Coproduct: codiag :: (Coproduct s) => s a a -> a
- Data.Rope.Util.Coproduct: counzip :: (Coproduct s, Coproduct s', Functor f) => s (f a) (f b) -> f (s' a b)
- Data.Rope.Util.Coproduct: data (:+) a b
- Data.Rope.Util.Coproduct: instance Applicative ((:+) a)
- Data.Rope.Util.Coproduct: instance Bifunctor :+
- Data.Rope.Util.Coproduct: instance Bifunctor :+:
- Data.Rope.Util.Coproduct: instance Coproduct :+
- Data.Rope.Util.Coproduct: instance Coproduct :+:
- Data.Rope.Util.Coproduct: instance Coproduct Either
- Data.Rope.Util.Coproduct: instance Functor ((:+) a)
- Data.Rope.Util.Coproduct: instance Functor ((:+:) a)
- Data.Rope.Util.Coproduct: instance Monad ((:+) a)
- Data.Rope.Util.Coproduct: left :: (Coproduct s) => a -> s a b
- Data.Rope.Util.Coproduct: right :: (Coproduct s) => b -> s a b
- Data.Rope.Util.Product: (:*:) :: !a -> !b -> :*: a b
- Data.Rope.Util.Product: both :: (Product p) => (a -> b) -> (a -> c) -> a -> p b c
- Data.Rope.Util.Product: bothC :: (Product p, Functor f) => (f a -> b) -> (f c -> d) -> f (p a c) -> p b d
- Data.Rope.Util.Product: class (Bifunctor p) => Product p
- Data.Rope.Util.Product: curry :: (Product p) => (p a b -> c) -> a -> b -> c
- Data.Rope.Util.Product: data (:*:) a b
- Data.Rope.Util.Product: diag :: (Product p) => a -> p a a
- Data.Rope.Util.Product: fst :: (Product p) => p a b -> a
- Data.Rope.Util.Product: instance (Monoid a, Monoid b) => Monoid (a :*: b)
- Data.Rope.Util.Product: instance (Reducer c a, Reducer c b) => Reducer c (a :*: b)
- Data.Rope.Util.Product: instance Bifunctor :*:
- Data.Rope.Util.Product: instance Comonad ((:*:) a)
- Data.Rope.Util.Product: instance Functor ((:*:) a)
- Data.Rope.Util.Product: instance Product (,)
- Data.Rope.Util.Product: instance Product :*:
- Data.Rope.Util.Product: pair :: (Product p) => a -> b -> p a b
- Data.Rope.Util.Product: snd :: (Product p) => p a b -> b
- Data.Rope.Util.Product: uncurry :: (Product p) => (a -> b -> c) -> p a b -> c
- Data.Rope.Util.Product: unzip :: (Product p, Functor f) => f (p a b) -> p (f a) (f b)
+ Data.Rope: break :: (Breakable a) => (a -> Bool) -> Rope -> (Rope, Rope)
+ Data.Rope: class Breakable a
+ Data.Rope: dropWhile :: (Breakable a) => (a -> Bool) -> Rope -> Rope
+ Data.Rope: span :: (Breakable a) => (a -> Bool) -> Rope -> (Rope, Rope)
+ Data.Rope: takeWhile :: (Breakable a) => (a -> Bool) -> Rope -> Rope
+ Data.Rope.Body: Offset :: Int -> Offset
+ Data.Rope.Body: getOffset :: Offset -> Int
+ Data.Rope.Body: instance Data Offset
+ Data.Rope.Body: instance Enum Offset
+ Data.Rope.Body: instance Eq Offset
+ Data.Rope.Body: instance Measured Offset Chunk
+ Data.Rope.Body: instance Monoid Offset
+ Data.Rope.Body: instance Num Offset
+ Data.Rope.Body: instance Ord Offset
+ Data.Rope.Body: instance Read Offset
+ Data.Rope.Body: instance Show Offset
+ Data.Rope.Body: instance Typeable Offset
+ Data.Rope.Body: newtype Offset
+ Data.Rope.Internal: break :: (Breakable a) => (a -> Bool) -> Rope -> (Rope, Rope)
+ Data.Rope.Internal: class Breakable a
+ Data.Rope.Internal: class Unpackable a
+ Data.Rope.Internal: dropWhile :: (Breakable a) => (a -> Bool) -> Rope -> Rope
+ Data.Rope.Internal: head :: (Unpackable a) => Rope -> a
+ Data.Rope.Internal: instance Breakable Word8
+ Data.Rope.Internal: instance Data Rope
+ Data.Rope.Internal: instance Eq Rope
+ Data.Rope.Internal: instance Measured Offset Rope
+ Data.Rope.Internal: instance Monoid Rope
+ Data.Rope.Internal: instance Ord Rope
+ Data.Rope.Internal: instance Reducer ByteString Rope
+ Data.Rope.Internal: instance Reducer Char Rope
+ Data.Rope.Internal: instance Reducer Chunk Rope
+ Data.Rope.Internal: instance Reducer Rope Rope
+ Data.Rope.Internal: instance Reducer String Rope
+ Data.Rope.Internal: instance Reducer Word8 Rope
+ Data.Rope.Internal: instance Reducer [Word8] Rope
+ Data.Rope.Internal: instance Show Rope
+ Data.Rope.Internal: instance Typeable Rope
+ Data.Rope.Internal: instance UTF8Bytes Rope Int
+ Data.Rope.Internal: instance Unpackable ByteString
+ Data.Rope.Internal: instance Unpackable Char
+ Data.Rope.Internal: instance Unpackable Chunk
+ Data.Rope.Internal: instance Unpackable Word8
+ Data.Rope.Internal: last :: (Unpackable a) => Rope -> a
+ Data.Rope.Internal: newtype Rope
+ Data.Rope.Internal: span :: (Breakable a) => (a -> Bool) -> Rope -> (Rope, Rope)
+ Data.Rope.Internal: takeWhile :: (Breakable a) => (a -> Bool) -> Rope -> Rope
+ Data.Rope.Internal: toString :: Rope -> String
+ Data.Rope.Internal: uncons :: (Unpackable a) => Rope -> Maybe (a, Rope)
+ Data.Rope.Internal: unpack :: (Unpackable a) => Rope -> [a]
+ Data.Rope.Internal: unsnoc :: (Unpackable a) => Rope -> Maybe (Rope, a)
- Data.Rope: data Rope a
+ Data.Rope: data Rope
- Data.Rope: drop :: (Annotation a) => Int -> Rope a -> Rope a
+ Data.Rope: drop :: Int -> Rope -> Rope
- Data.Rope: empty :: (Monoid m) => Rope m
+ Data.Rope: empty :: Rope
- Data.Rope: fromByteString :: (Reducer ByteString m) => ByteString -> Rope m
+ Data.Rope: fromByteString :: ByteString -> Rope
- Data.Rope: fromChar :: (Reducer ByteString m) => Char -> Rope m
+ Data.Rope: fromChar :: Char -> Rope
- Data.Rope: fromChunks :: (Reducer ByteString m) => [ByteString] -> Rope m
+ Data.Rope: fromChunks :: [ByteString] -> Rope
- Data.Rope: fromLazyByteString :: (Reducer ByteString m) => ByteString -> Rope m
+ Data.Rope: fromLazyByteString :: ByteString -> Rope
- Data.Rope: fromString :: (Reducer ByteString m) => String -> Rope m
+ Data.Rope: fromString :: String -> Rope
- Data.Rope: fromWord8 :: (Reducer ByteString m) => Word8 -> Rope m
+ Data.Rope: fromWord8 :: Word8 -> Rope
- Data.Rope: fromWords :: (Reducer ByteString m) => [Word8] -> Rope m
+ Data.Rope: fromWords :: [Word8] -> Rope
- Data.Rope: head :: (Unpackable a) => Rope m -> a
+ Data.Rope: head :: (Unpackable a) => Rope -> a
- Data.Rope: last :: (Unpackable a) => Rope m -> a
+ Data.Rope: last :: (Unpackable a) => Rope -> a
- Data.Rope: length :: Rope m -> Int
+ Data.Rope: length :: Rope -> Int
- Data.Rope: null :: Rope m -> Bool
+ Data.Rope: null :: Rope -> Bool
- Data.Rope: splitAt :: (Annotation a) => Int -> Rope a -> (Rope a, Rope a)
+ Data.Rope: splitAt :: Int -> Rope -> (Rope, Rope)
- Data.Rope: take :: (Annotation a) => Int -> Rope a -> Rope a
+ Data.Rope: take :: Int -> Rope -> Rope
- Data.Rope: toChunks :: Rope m -> [ByteString]
+ Data.Rope: toChunks :: Rope -> [ByteString]
- Data.Rope: toLazyByteString :: Rope m -> ByteString
+ Data.Rope: toLazyByteString :: Rope -> ByteString
- Data.Rope: toString :: Rope m -> String
+ Data.Rope: toString :: Rope -> String
- Data.Rope: uncons :: (Unpackable a, Annotation m) => Rope m -> Maybe (a, Rope m)
+ Data.Rope: uncons :: (Unpackable a) => Rope -> Maybe (a, Rope)
- Data.Rope: unpack :: (Unpackable a) => Rope m -> [a]
+ Data.Rope: unpack :: (Unpackable a) => Rope -> [a]
- Data.Rope: unsnoc :: (Unpackable a, Annotation m) => Rope m -> Maybe (Rope m, a)
+ Data.Rope: unsnoc :: (Unpackable a) => Rope -> Maybe (Rope, a)
- Data.Rope.Body: measureBody :: (Measured Count a) => FingerTree Count a -> Int
+ Data.Rope.Body: measureBody :: (Measured Offset a) => FingerTree Offset a -> Int
- Data.Rope.Body: type Body = FingerTree Count Chunk
+ Data.Rope.Body: type Body = FingerTree Offset Chunk
- Data.Rope.Internal: Rope :: !Body -> a -> Rope a
+ Data.Rope.Internal: Rope :: Body -> Rope
- Data.Rope.Internal: body :: Rope a -> Body
+ Data.Rope.Internal: body :: Rope -> Body
- Data.Rope.Internal: drop :: (Annotation a) => Int -> Rope a -> Rope a
+ Data.Rope.Internal: drop :: Int -> Rope -> Rope
- Data.Rope.Internal: empty :: (Monoid m) => Rope m
+ Data.Rope.Internal: empty :: Rope
- Data.Rope.Internal: fromByteString :: (Reducer ByteString m) => ByteString -> Rope m
+ Data.Rope.Internal: fromByteString :: ByteString -> Rope
- Data.Rope.Internal: fromChar :: (Reducer ByteString m) => Char -> Rope m
+ Data.Rope.Internal: fromChar :: Char -> Rope
- Data.Rope.Internal: fromChunks :: (Reducer ByteString m) => [ByteString] -> Rope m
+ Data.Rope.Internal: fromChunks :: [ByteString] -> Rope
- Data.Rope.Internal: fromLazyByteString :: (Reducer ByteString m) => ByteString -> Rope m
+ Data.Rope.Internal: fromLazyByteString :: ByteString -> Rope
- Data.Rope.Internal: fromString :: (Reducer ByteString m) => String -> Rope m
+ Data.Rope.Internal: fromString :: String -> Rope
- Data.Rope.Internal: fromWord8 :: (Reducer ByteString m) => Word8 -> Rope m
+ Data.Rope.Internal: fromWord8 :: Word8 -> Rope
- Data.Rope.Internal: fromWords :: (Reducer ByteString m) => [Word8] -> Rope m
+ Data.Rope.Internal: fromWords :: [Word8] -> Rope
- Data.Rope.Internal: length :: Rope m -> Int
+ Data.Rope.Internal: length :: Rope -> Int
- Data.Rope.Internal: null :: Rope m -> Bool
+ Data.Rope.Internal: null :: Rope -> Bool
- Data.Rope.Internal: pack :: (Packable a, Annotation m) => a -> Rope m
+ Data.Rope.Internal: pack :: (Reducer a Rope) => a -> Rope
- Data.Rope.Internal: splitAt :: (Annotation a) => Int -> Rope a -> (Rope a, Rope a)
+ Data.Rope.Internal: splitAt :: Int -> Rope -> (Rope, Rope)
- Data.Rope.Internal: take :: (Annotation a) => Int -> Rope a -> Rope a
+ Data.Rope.Internal: take :: Int -> Rope -> Rope
- Data.Rope.Internal: toChunks :: Rope m -> [ByteString]
+ Data.Rope.Internal: toChunks :: Rope -> [ByteString]
- Data.Rope.Internal: toLazyByteString :: Rope m -> ByteString
+ Data.Rope.Internal: toLazyByteString :: Rope -> ByteString
Files
- Data/Rope.hs +29/−39
- Data/Rope/Body.hs +8/−8
- Data/Rope/Internal.hs +208/−318
- Data/Rope/Unpackable.hs +0/−120
- Data/Rope/Util/Bifunctor.hs +0/−22
- Data/Rope/Util/Comonad.hs +0/−11
- Data/Rope/Util/Coproduct.hs +0/−84
- Data/Rope/Util/Product.hs +0/−77
- Data/Rope/Util/Reducer.hs +1/−1
- LICENSE +30/−1
- rope.cabal +3/−9
Data/Rope.hs view
@@ -1,38 +1,33 @@-module Data.Rope - ( +module Data.Rope ( -- * Size Rope- , length -- :: Rope m -> Int- , null -- :: Rope m -> Bool- -- * Splicing- , Reducer(..)+ , length -- :: Rope -> Int+ , null -- :: Rope -> Bool -- * Slicing- , Annotation(..)- , elide -- :: Annotation m => Int -> Int -> Rope m -> Rope m- , splitAt -- :: Annotation m => Int -> Rope m -> (Rope m, Rope m)- , take -- :: Annotation m => Int -> Rope m -> Rope m- , drop -- :: Annotation m => Int -> Rope m -> Rope m+ , Breakable(..)+ , splitAt -- :: Int -> Rope -> (Rope, Rope)+ , take -- :: Int -> Rope -> Rope+ , drop -- :: Int -> Rope -> Rope -- * Walking- , Unpackable(..)- -- * Packing 'Rope'- -- ** Polymorphic construction- , Packable(..)- -- ** Explicit construction- , empty -- :: Monoid m => Rope m- , fromByteString -- :: Annotation m => ByteString -> Rope m- , fromChunks -- :: Annotation m => [ByteString] -> Rope m- , fromLazyByteString -- :: Annotation m => L.ByteString -> Rope m- , fromWords -- :: Annotation m => [Word8] -> Rope m- , fromChar -- :: Annotation m => Char -> Rope m- , fromWord8 -- :: Annotation m => Word8 -> Rope m- , fromString -- :: Annotation m => String -> Rope m+ -- ** construction+ , Reducer(..)+ , empty -- :: Rope+ , fromByteString -- :: ByteString -> Rope+ , fromChunks -- :: [ByteString] -> Rope+ , fromLazyByteString -- :: L.ByteString -> Rope+ , fromWords -- :: [Word8] -> Rope+ , fromChar -- :: Char -> Rope+ , fromWord8 -- :: Word8 -> Rope+ , fromString -- :: String -> Rope -- * Deconstructing 'Rope's- , toChunks -- :: Rope m -> [ByteString]- , toLazyByteString -- :: Rope m -> L.ByteString- , toString -- :: Rope m -> String+ , Unpackable(..)+ , toChunks -- :: Rope -> [ByteString]+ , toLazyByteString -- :: Rope -> L.ByteString+ , toString -- :: Rope -> String ) where import Prelude hiding (null,head,length,drop,take,splitAt, last)+import Data.Rope.Util.Reducer (Reducer(..)) import Data.Rope.Internal ( Rope , empty@@ -45,16 +40,11 @@ , fromChar , fromWord8 , fromString+ , toString+ , toChunks , toLazyByteString- , Packable(..)- , Annotation(..)- , elide, splitAt, take, drop)-import Data.Rope.Unpackable (Unpackable(..))-import Data.Rope.Util.Reducer (Reducer(..))-import Data.ByteString (ByteString)--toString :: Rope m -> String-toString = unpack--toChunks :: Rope m -> [ByteString]-toChunks = unpack+ , Breakable(..)+ , Unpackable(..)+ , splitAt+ , take+ , drop)
Data/Rope/Body.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving, DeriveDataTypeable, MultiParamTypeClasses, FlexibleContexts, TypeSynonymInstances #-} module Data.Rope.Body ( Body- , Count(..)+ , Offset(..) , Chunk(..) , measureBody , cons'@@ -16,21 +16,21 @@ import Data.Rope.Util.Reducer import Data.ByteString (ByteString, null, length) -newtype Count = Count { getCount :: Int } deriving (Eq,Ord,Num,Show,Read,Enum,Data,Typeable)+newtype Offset = Offset { getOffset :: Int } deriving (Eq,Ord,Num,Show,Read,Enum,Data,Typeable) -instance Monoid Count where+instance Monoid Offset where mempty = 0 mappend = (+) newtype Chunk = Chunk { unchunk :: ByteString } deriving (Eq,Ord,Show,Read,Data,Typeable) -instance Measured Count Chunk where- measure = Count . length . unchunk+instance Measured Offset Chunk where+ measure = Offset . length . unchunk -type Body = FingerTree Count Chunk +type Body = FingerTree Offset Chunk -measureBody :: Measured Count a => FingerTree Count a -> Int-measureBody = getCount . measure+measureBody :: Measured Offset a => FingerTree Offset a -> Int+measureBody = getOffset . measure cons' :: ByteString -> Body -> Body b `cons'` t | null b = t
Data/Rope/Internal.hs view
@@ -1,200 +1,156 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, TypeSynonymInstances, MultiParamTypeClasses, UndecidableInstances, TypeOperators #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances, TypeSynonymInstances, MultiParamTypeClasses, UndecidableInstances, TypeOperators, DeriveDataTypeable #-} module Data.Rope.Internal ( Rope(..) -- * Construction- , cons8 -- :: (ByteString `Reducer` m) => Word8 -> Rope m -> Rope m- , empty -- :: Monoid m => Rope m - , fromChunks -- :: (ByteString `Reducer` m) => [ByteString] -> Rope m- , fromByteString -- :: (ByteString `Reducer` m) => ByteString -> Rope m - , fromLazyByteString -- :: (ByteString `Reducer` m) => L.ByteString -> Rope m - , fromString -- :: (ByteString `Reducer` m) => String -> Rope m- , fromWords -- :: (ByteString `Reducer` m) => [Word8] -> Rope m- , fromChar -- :: (ByteString `Reducer` m) => Char -> Rope m- , fromWord8 -- :: (ByteString `Reducer` m) => Word8 -> Rope m+ , pack -- :: a `Reducer` Rope => a -> Roe+ , empty -- :: Rope+ , fromChunks -- :: [ByteString] -> Rope+ , fromByteString -- :: ByteString -> Rope+ , fromLazyByteString -- :: L.ByteString -> Rope+ , fromString -- :: String -> Rope+ , fromWords -- :: [Word8] -> Rope+ , fromChar -- :: Char -> Rope+ , fromWord8 -- :: Word8 -> Rope -- * Analysis- , length -- :: Rope m -> Int- , null -- :: Rope m -> Bool- , body -- :: Rope a -> Body+ , length -- :: Rope -> Int+ , null -- :: Rope -> Bool -- * Deconstruction- , toChunks -- :: Rope m -> [S.ByteString]- , toLazyByteString -- :: Rope m -> L.ByteString+ , toChunks -- :: Rope -> [ByteString]+ , toString -- :: Rope -> String+ , toLazyByteString -- :: Rope -> L.ByteString -- * Cutting - , Annotation(..)- , elide , splitAt , take , drop- , uncons8- , unsnoc8+ -- * Unpacking+ , Unpackable(..)+ , Breakable(..)+ -- Utility , w2c- -- * Pasting- , Packable(..)- , break8- , findIndexOrEnd+ , findIndexOrEnd -- :: (Word8 -> Bool) -> ByteString -> Int ) where -import Prelude hiding (length, foldl, null, length, splitAt, take, drop, fst, snd) +import Prelude hiding (head, last, length, foldl, null, length, splitAt, take, drop, break, span)+import qualified Prelude+ import Control.Applicative hiding (empty)-import Control.Monad.Writer.Class (MonadWriter, tell, pass, listen) -import Data.Data (Data(..), DataType, Constr, Fixity(..), mkConstr, mkDataType, constrIndex, gcast1)-import Data.Typeable (TyCon, Typeable1(..), mkTyCon, mkTyConApp)+import Data.Data (Data(..), DataType, Constr, Fixity(..), mkConstr, mkDataType, constrIndex)+import Data.Typeable (Typeable(..)) import Data.FingerTree (ViewL(..),ViewR(..),viewl,viewr,(<|),(|>), Measured(..), (><)) import qualified Data.FingerTree as F (empty, split, null, singleton) -import Data.Foldable (Foldable, foldl) import qualified Data.Foldable as F -import Data.Traversable (Traversable)-import qualified Data.Traversable as T- import Data.Monoid import Data.Rope.Body--- import Data.Rope.Util.Bifunctor-import Data.Rope.Util.Comonad import Data.Rope.Util.Reducer (Reducer, cons, snoc, unit)-import Data.Rope.Util.Product--- import Data.Rope.Util.Coproduct import Data.Word (Word8) --- import Codec.Binary.UTF8.Generic (UTF8Bytes)--- import qualified Codec.Binary.UTF8.Generic as UTF8Bytes- import GHC.Base (unsafeChr)--- import GHC.IOBase--- import GHC.Ptr (Ptr(..)) import Foreign.Ptr import Foreign.ForeignPtr import Foreign.Storable (peek) -import qualified Data.ByteString as S (null, splitAt, take, drop, length, singleton)+import qualified Data.ByteString as S (null, splitAt, take, drop, length, singleton, unpack, last) import Data.ByteString.Internal (ByteString(..), inlinePerformIO) import qualified Data.ByteString.Unsafe as S (unsafeTail, unsafeHead)-import qualified Data.ByteString.UTF8 as U--- import qualified Data.ByteString.Char8 as SC (pack)-import qualified Data.ByteString.Lazy as L (ByteString, pack, fromChunks, drop, take, splitAt, toChunks)-import qualified Data.ByteString.Lazy.UTF8 as LU+import qualified Data.ByteString.UTF8 as U (fromString)+import qualified Data.ByteString.Lazy as L (ByteString, pack, fromChunks, toChunks, elemIndex)+import qualified Data.ByteString.Lazy.UTF8 as LU (fromString, toString) --- a Buffer is a fingertree of non-empty chunks-data Rope a = Rope !Body a- deriving (Show)+import Codec.Binary.UTF8.Generic (UTF8Bytes)+import qualified Codec.Binary.UTF8.Generic as UTF8Bytes -body :: Rope a -> Body-body (Rope b _) = b-{-# INLINE body #-}+-- a Buffer is a fingertree of non-empty chunks+newtype Rope = Rope { body :: Body } + deriving (Show, Typeable) -instance Monoid a => Monoid (Rope a) where+instance Monoid Rope where mempty = empty- Rope t m `mappend` Rope t' m' = Rope (t >< t') (m `mappend` m')+ Rope t `mappend` Rope t' = Rope (t >< t') -instance Eq a => Eq (Rope a) where+instance Eq Rope where a == b = measure (body a) == measure (body b) && toLazyByteString a == toLazyByteString b - && extract a == extract b -instance Measured Count (Rope a) where- measure (Rope m _) = measure m --instance Functor Rope where- fmap f (Rope b a) = Rope b (f a)---- monadic and applicative rope actions build up a fingertree as a result, and can be used like a fast string writer-instance Applicative Rope where- pure = Rope mempty- Rope m f <*> Rope m' a = Rope (m `mappend` m') (f a)--instance Monad Rope where- return = Rope mempty- Rope m a >>= f = let Rope m' b = f a in Rope (m `mappend` m') b- -instance MonadWriter (Rope ()) Rope where- tell (Rope m _) = Rope m ()- listen (Rope m a) = Rope m (a, Rope m ())- pass (Rope m (a,f)) = Rope (body (f (Rope m ()))) a---- on the other hand, the context-comonadic actions on ropes can be used to provide slicing of annotated ropes--- however, these two structures are largely unrelated, so make sure you know the purpose of your rope!--instance Comonad Rope where- extract (Rope _ a) = a - duplicate (Rope b a) = Rope b (Rope b a)- extend f r = Rope (body r) (f r)+instance Ord Rope where+ a `compare` b = toLazyByteString a `compare` toLazyByteString b -instance Foldable Rope where- foldr f z (Rope _ a) = f a z- foldr1 _ (Rope _ a) = a - foldl f z (Rope _ a) = f z a- foldl1 _ (Rope _ a) = a- foldMap f (Rope _ a) = f a+instance Measured Offset Rope where+ measure = measure . body -instance Traversable Rope where- traverse f (Rope b a) = Rope b <$> f a+pack :: Reducer a Rope => a -> Rope+pack = unit+{-# INLINE pack #-} -empty :: Monoid m => Rope m-empty = Rope F.empty mempty+empty :: Rope+empty = Rope F.empty+{-# INLINE empty #-} -fromChunks :: (ByteString `Reducer` m) => [ByteString] -> Rope m-fromChunks = foldr (\l (Rope t m) -> Rope (l `cons'` t) (l `cons` m)) mempty+fromChunks :: [ByteString] -> Rope+fromChunks = foldr (\l (Rope t) -> Rope (l `cons'` t)) mempty {-# INLINE fromChunks #-} -toChunks :: Rope m -> [ByteString]+toChunks :: Rope -> [ByteString] toChunks r = unchunk <$> F.toList (body r) {-# INLINE toChunks #-} -toLazyByteString :: Rope m -> L.ByteString+toLazyByteString :: Rope -> L.ByteString toLazyByteString = L.fromChunks . toChunks {-# INLINE toLazyByteString #-} -length :: Rope m -> Int+toString :: Rope -> String+toString = unpack++length :: Rope -> Int length = measureBody . body {-# INLINE length #-} -null :: Rope m -> Bool+null :: Rope -> Bool null = F.null . body {-# INLINE null #-} -fromByteString :: (ByteString `Reducer` m) => ByteString -> Rope m +fromByteString :: ByteString -> Rope fromByteString b | S.null b = mempty - | otherwise = Rope (F.singleton (Chunk b)) (unit b)+ | otherwise = Rope (F.singleton (Chunk b)) {-# INLINE fromByteString #-} -- NB this requires a strict bytestring reducer, but a lazy bytestring-fromLazyByteString :: (ByteString `Reducer` m) => L.ByteString -> Rope m -fromLazyByteString = foldr (\l (Rope t m) -> Rope (Chunk l <| t) (l `cons` m)) mempty . L.toChunks+fromLazyByteString :: L.ByteString -> Rope+fromLazyByteString = foldr (\l (Rope t) -> Rope (Chunk l <| t)) mempty . L.toChunks {-# INLINE fromLazyByteString #-} -- utf8 encode chunks of the string-fromString :: (ByteString `Reducer` m) => String -> Rope m+fromString :: String -> Rope fromString = fromLazyByteString . LU.fromString {-# INLINE fromString #-} -fromWords :: (ByteString `Reducer` m) => [Word8] -> Rope m+fromWords :: [Word8] -> Rope fromWords = fromLazyByteString . L.pack {-# INLINE fromWords #-} -fromChar :: (ByteString `Reducer` m) => Char -> Rope m-fromChar c = Rope (F.singleton (Chunk b)) (unit b)- where b = U.fromString [c]+fromChar :: Char -> Rope+fromChar c = Rope (F.singleton (Chunk (U.fromString [c]))) {-# INLINE fromChar #-} -fromWord8 :: (ByteString `Reducer` m) => Word8 -> Rope m-fromWord8 b = Rope (F.singleton (Chunk s)) (unit s)- where s = S.singleton b+fromWord8 :: Word8 -> Rope+fromWord8 b = Rope (F.singleton (Chunk (S.singleton b))) {-# INLINE fromWord8 #-} -cons8 :: (ByteString `Reducer` m) => Word8 -> Rope m -> Rope m-cons8 a (Rope t m) = case viewl t of- Chunk c :< cs | S.length c < 16 -> Rope (Chunk (mappend b c) <| cs) (cons b m)- _ -> Rope (Chunk b <| t) (cons b m)+cons8 :: Word8 -> Rope -> Rope+cons8 a (Rope t) = case viewl t of+ Chunk c :< cs | S.length c < 16 -> Rope (Chunk (mappend b c) <| cs)+ _ -> Rope (Chunk b <| t) where b = S.singleton a {-# INLINE cons8 #-} -instance (Annotation a, Data a) => Data (Rope a) where+instance Data Rope where gfoldl f z r = case uncons8 r of Nothing -> z empty Just (x,xs) -> z cons8 `f` x `f` xs @@ -209,7 +165,6 @@ | otherwise = consConstr dataTypeOf _ = ropeDataType- dataCast1 f = gcast1 f emptyConstr, consConstr :: Constr emptyConstr = mkConstr ropeDataType "empty" [] Prefix@@ -218,138 +173,38 @@ ropeDataType :: DataType ropeDataType = mkDataType "Data.Rope.Internal.Rope" [emptyConstr, consConstr] -ropeTc :: TyCon-ropeTc = mkTyCon "Rope"--instance Typeable1 Rope where - typeOf1 _ = mkTyConApp ropeTc []---- HTTP--- import Network.BufferType--- import Network.TCP--class (ByteString `Reducer` a) => Annotation a where- elide' :: Int -> Int -> Rope a -> a--- TODO--- elide' f l ra = fst (extract rlmr) `mappend` drop l (snd <$> rlmr) where--- rlmr = splitAt f (duplicate ra)-- splitAt' :: Int -> Rope a -> (a, a)-- take' :: Int -> Rope a -> a- take' n = fst . splitAt' n-- drop' :: Int -> Rope a -> a- drop' n = snd . splitAt' n --elide :: Annotation a => Int -> Int -> Rope a -> Rope a-elide f l = elide' f l . duplicate--splitAt :: Annotation a => Int -> Rope a -> (Rope a, Rope a)-splitAt n = splitAt' n . duplicate--take :: Annotation a => Int -> Rope a -> Rope a-take n = take' n . duplicate--drop :: Annotation a => Int -> Rope a -> Rope a-drop n = drop' n . duplicate--instance Annotation () where- elide' _ _ _ = () - splitAt' _ _ = ((),())- take' _ _ = ()- drop' _ _ = ()---- Int -> Int -> Rope (a,b) -> (a,b))--- Int -> Int -> Rope (a,b) -> ((a,a),(b,b))-instance (Annotation a, Annotation b) => Annotation (a, b) where- elide' x y = bothC (elide' x y) (elide' x y)- splitAt' x (Rope t (a,b)) = ((a',b'),(a'',b'')) where- (a',a'') = splitAt' x (Rope t a)- (b',b'') = splitAt' x (Rope t b)- take' x = bothC (take' x) (take' x) - drop' x = bothC (drop' x) (drop' x)--instance (Annotation a, Annotation b) => Annotation (a :*: b) where- elide' x y = bothC (elide' x y) (elide' x y)- splitAt' x (Rope t (a :*: b)) = ((a' :*: b'),(a'' :*: b'')) where- (a',a'') = splitAt' x (Rope t a)- (b',b'') = splitAt' x (Rope t b)- take' x = bothC (take' x) (take' x) - drop' x = bothC (drop' x) (drop' x)-{---- relies on the fact that ropes are cozippable having only one 'hole'-eitherC :: Coproduct s => (Rope a -> b) -> (Rope c -> d) -> Rope (s a c) -> s b d-eitherC f g (Rope t sab) = bimap (f . Rope t) (g . Rope t) sab---- TODO---instance (Annotation a, Annotation b) => Annotation (Either a b) where- elide' x y = eitherC (elide' x y) (elide' x y)- splitAt' x = eitherC (splitAt' x) (splitAt' x)- take' x = eitherC (take' x) (take' x)- drop' x = eitherC (drop' x) (drop' x)--instance (Annotation a, Annotation b) => Annotation (a :+ b) where- elide' x y = eitherC (elide' x y) (elide' x y)- splitAt' x = eitherC (splitAt' x) (splitAt' x)- take' x = eitherC (take' x) (take' x)- drop' x = eitherC (drop' x) (drop' x)--instance (Annotation a, Annotation b) => Annotation (a :+: b) where- elide' x y = eitherC (elide' x y) (elide' x y)- splitAt' x = eitherC (splitAt' x) (splitAt' x)- take' x = eitherC (take' x) (take' x)- drop' x = eitherC (drop' x) (drop' x)--}--instance Annotation ByteString where- elide' = undefined- splitAt' n rb = S.splitAt n (extract rb)- take' n rb = S.take n (extract rb)- drop' n rb = S.drop n (extract rb)--instance Annotation L.ByteString where- elide' = undefined- splitAt' n rb = L.splitAt (fromIntegral n) (extract rb)- take' n rb = L.take (fromIntegral n) (extract rb)- drop' n rb = L.drop (fromIntegral n) (extract rb)--instance Annotation Body where- elide' = undefined- splitAt' 0 rf = (mempty, extract rf)- splitAt' n rf - | n >= measureBody f = (f, mempty)- | otherwise = (x `snoc'` y', y'' `cons'` z)+splitAt :: Int -> Rope -> (Rope,Rope)+splitAt n (Rope f)+ | n <= 0 = (mempty, Rope f)+ | n >= measureBody f = (Rope f, mempty)+ | otherwise = (Rope (x `snoc'` y'), Rope (y'' `cons'` z)) where- f = extract rf- (x,yz) = F.split (> Count n) (extract rf)+ (x,yz) = F.split (> Offset n) f Chunk y :< z = viewl yz (y', y'') = S.splitAt (n - measureBody x) y -instance Annotation a => Annotation (Rope a) where- elide' = undefined- splitAt' n rra = (Rope t a, Rope t' a') where- (t,t') = splitAt' n (body <$> rra)- (a,a') = splitAt' n (extract rra)+take :: Int -> Rope -> Rope+take n = fst . splitAt n+{-# INLINE take #-} -{---- DO NOT USE! For testing purposes only. You'll have terrible O(n^2) asymptotics!-instance Ord k => Annotation (Map Int v) where- splitAt k a = (l, M.mapKeysMonotonic (subtract k) $ maybe id (M.insert k) r) where (l,m,r) = M.splitLookup k (extract a)+drop :: Int -> Rope -> Rope+drop n = snd . splitAt n+{-# INLINE drop #-} --- DO NOT USE! For testing purposes only. You'll have terrible O(n^2) asymptotics!-instance Ord k => Annotation (Set Int) where- splitAt k s = (l, S.mapKeysMonotonic (subtract k) $ maybe id S.insert r) where- (l,m,r) = S.splitLookup k (extract a)--}+class Breakable a where+ break :: (a -> Bool) -> Rope -> (Rope, Rope)+ span :: (a -> Bool) -> Rope -> (Rope, Rope)+ takeWhile :: (a -> Bool) -> Rope -> Rope+ dropWhile :: (a -> Bool) -> Rope -> Rope -break8 :: Annotation m => (Word8 -> Bool) -> Rope m -> (Rope m, Rope m)-break8 f r = (Rope t' a', Rope t'' a'')+ span f = break (not . f)+ takeWhile f = fst . span f+ dropWhile f = snd . span f++break8 :: (Word8 -> Bool) -> Rope -> (Rope, Rope)+break8 f r = (Rope t', Rope t'') where (t',t'') = break' (body r)- (a',a'') = splitAt' (measureBody t') r break' ccs = case viewl ccs of EmptyL -> (F.empty, F.empty) Chunk c :< cs -> case findIndexOrEnd f c of @@ -357,7 +212,11 @@ n | n < S.length c -> (F.singleton (Chunk (S.take n c)), Chunk (S.drop n c) <| cs) | otherwise -> let (cs', cs'') = break' cs in (Chunk c <| cs', cs'')+{-# INLINE break8 #-} +instance Breakable Word8 where+ break = break8+ findIndexOrEnd :: (Word8 -> Bool) -> ByteString -> Int findIndexOrEnd k (PS x s l) = inlinePerformIO $ withForeignPtr x $ \f -> go (f `plusPtr` s) 0 where@@ -369,105 +228,136 @@ else go (ptr `plusPtr` 1) (n+1) {-# INLINE findIndexOrEnd #-} -uncons8 :: Annotation m => Rope m -> Maybe (Word8, Rope m)+uncons8 :: Rope -> Maybe (Word8, Rope) uncons8 r = case viewl (body r) of- Chunk c :< cs -> Just (S.unsafeHead c, Rope (S.unsafeTail c `cons'` cs) (drop' 1 r))+ Chunk c :< cs -> Just (S.unsafeHead c, Rope (S.unsafeTail c `cons'` cs)) _ -> Nothing+{-# INLINE uncons8 #-} -unsnoc8 :: Annotation m => Rope m -> Maybe (Rope m, Word8)+unsnoc8 :: Rope -> Maybe (Rope, Word8) unsnoc8 r = case viewr (body r) of- cs :> Chunk c -> Just (Rope (cs `snoc'` S.unsafeTail c) (take' (length r - 1) r), S.unsafeHead c)+ cs :> Chunk c -> Just (Rope (cs `snoc'` S.unsafeTail c), S.unsafeHead c) _ -> Nothing---{--instance Annotation m => UTF8Bytes (Rope m) Int where- bsplit n = splitAt n- bdrop n = drop n - buncons = uncons8- elemIndex = undefined- null = undefined- pack = undefined- tail r = case viewl (body r) of- Chunk a :< as -> Rope (S.unsafeTail a `cons'` as) (drop' 1 r)- EmptyL -> error "Codec.Binary.UTF8.Generic.UTF8Bytes.tail (Kata.Rope m): error empty list"--}+{-# INLINE unsnoc8 #-} w2c :: Word8 -> Char w2c = unsafeChr . fromIntegral+{-# INLINE w2c #-} -{---- towards interoperating directly with Network.HTTP--- unfortunately the machinery needed to implement HStream isn't exported, so this doesn't get us anywhere-instance Annotation m => BufferType (Rope m) where- bufferOps = BufferOp- { buf_hGet = \h i -> singleton <$> buf_hGet lazyBufferOp h i- , buf_hGetContents = \h -> singleton <$> buf_hGetContents lazyBufferOp h- , buf_hPut = \h b -> buf_hPut lazyBufferOp h (toLazy b)- , buf_hGetLine = \h -> singleton <$> buf_hGetLine lazyBufferOp h- , buf_empty = mempty- , buf_append = mappend- , buf_concat = mconcat- , buf_fromStr = fromLazyByteString . buf_fromStr lazyBufferOp- , buf_toStr = buf_toStr lazyBufferOp . toLazy- , buf_snoc = snoc- , buf_splitAt = splitAt- , buf_span = \f -> break8 (not . f . w2c)- , buf_isLineTerm = (unit (SC.pack "\r\n") ==)- , buf_isEmpty = null- }--}+instance Reducer Char Rope where+ unit = fromChar+ cons a (Rope t) = case viewl t of+ Chunk c :< cs | S.length c < 16 -> Rope (Chunk (mappend b c) <| cs)+ _ -> Rope (Chunk b <| t)+ where b = U.fromString [a]+ snoc (Rope t) a = case viewr t of+ cs :> Chunk c | S.length c < 16 -> Rope (cs |> Chunk (mappend c b))+ _ -> Rope (t |> Chunk b)+ where b = U.fromString [a] -class Packable a where- pack :: Annotation m => a -> Rope m- packl :: Annotation m => a -> Rope m -> Rope m- packr :: Annotation m => Rope m -> a -> Rope m+instance Reducer Word8 Rope where+ unit = fromWord8+ cons = cons8 + snoc (Rope t) a = case viewr t of+ cs :> Chunk c | S.length c < 16 -> Rope (cs |> Chunk (mappend c b))+ _ -> Rope (t |> Chunk b)+ where b = S.singleton a - packl a r = pack a `mappend` r- packr r a = r `mappend` pack a+instance Reducer Rope Rope where+ unit = id -instance Packable Char where- pack = fromChar- packl a (Rope t m) = case viewl t of- Chunk c :< cs | S.length c < 16 -> Rope (Chunk (mappend b c) <| cs) (cons b m)- _ -> Rope (Chunk b <| t) (cons b m)- where b = U.fromString [a]+instance Reducer String Rope where+ unit = fromString - packr (Rope t m) a = case viewr t of- cs :> Chunk c | S.length c < 16 -> Rope (cs |> Chunk (mappend c b)) (snoc m b)- _ -> Rope (t |> Chunk b) (snoc m b)- where b = U.fromString [a]+instance Reducer [Word8] Rope where+ unit = fromWords -instance Packable Word8 where- pack = fromWord8- packl = cons8 +instance Reducer ByteString Rope where+ unit = fromByteString - packr (Rope t m) a = case viewr t of- cs :> Chunk c | S.length c < 16 -> Rope (cs |> Chunk (mappend c b)) (snoc m b)- _ -> Rope (t |> Chunk b) (snoc m b)- where b = S.singleton a+instance Reducer L.ByteString Rope where+ unit = fromLazyByteString --- note this isn't a no-op, you can change annotations!-instance Annotation n => Packable (Rope n) where- pack (Rope t _) = Rope t (foldl (\a b -> a `snoc` unchunk b) mempty t)+instance Reducer Chunk Rope where+ unit = fromByteString . unchunk -instance Packable String where- pack = fromString -instance Packable [Word8] where- pack = fromWords+instance UTF8Bytes Rope Int where+ bsplit = splitAt + bdrop = drop + buncons f = case viewl (body f) of+ Chunk c :< cs -> Just (S.unsafeHead c, Rope (S.unsafeTail c `cons' ` cs))+ EmptyL -> Nothing+ tail (Rope f) = case viewl f of+ Chunk c :< cs -> Rope (S.unsafeTail c `cons'`cs)+ EmptyL -> errorEmptyList "tail"+ elemIndex b = fmap fromIntegral . L.elemIndex b . L.fromChunks . map unchunk . F.toList . body+ pack = Rope . foldr (\l r -> Chunk l <| r) F.empty . L.toChunks . L.pack+ empty = Rope F.empty+ null = F.null . body -instance Packable ByteString where- pack = fromByteString -instance Packable L.ByteString where- pack = fromLazyByteString+class Unpackable a where+ unpack :: Rope -> [a] -instance Packable Chunk where- pack = fromByteString . unchunk + head :: Rope -> a+ head = Prelude.head . unpack -instance (Packable a, Annotation m) => Reducer a (Rope m) where- unit = pack- cons = packl- snoc = packr+ last :: Rope -> a++ uncons :: Rope -> Maybe (a, Rope)+ unsnoc :: Rope -> Maybe (Rope, a)++instance Unpackable Word8 where+ unpack = concatMap (S.unpack . unchunk) . F.toList . body+ head t = case viewl (body t) of+ Chunk a :< _ -> S.unsafeHead a+ EmptyL -> errorEmptyList "head"+ last t = case viewr (body t) of+ _ :> Chunk a -> S.last a+ EmptyR -> errorEmptyList "last"+ uncons = uncons8+ unsnoc = unsnoc8++instance Unpackable Char where+ unpack = LU.toString . toLazyByteString+ head = Prelude.head . unpack+ last = undefined -- TODO+ uncons r@(Rope t) = case UTF8Bytes.decode (Rope t) of + Nothing -> Nothing+ Just (a,n) -> Just (a, drop n r)+ unsnoc = undefined -- TODO++instance Unpackable ByteString where+ unpack = map unchunk . F.toList . body+ head r = case viewl (body r) of+ Chunk a :< _ -> a+ _ -> errorEmptyList "head"+ last r = case viewr (body r) of+ _ :> Chunk a -> a+ _ -> errorEmptyList "last" + uncons r = case viewl (body r) of+ Chunk a :< as -> Just (a, Rope as)+ EmptyL -> Nothing+ unsnoc r = case viewr (body r) of+ as :> Chunk a -> Just (Rope as, a)+ EmptyR -> Nothing++instance Unpackable Chunk where+ unpack = F.toList . body+ head r = case viewl (body r) of+ a :< _ -> a+ _ -> errorEmptyList "head"+ last r = case viewr (body r) of+ _ :> a -> a+ _ -> errorEmptyList "last"+ uncons r = case viewl (body r) of+ Chunk a :< as -> Just (Chunk a, Rope as)+ EmptyL -> Nothing+ unsnoc r = case viewr (body r) of+ as :> Chunk a -> Just (Rope as, Chunk a)+ EmptyR -> Nothing++errorEmptyList :: String -> a+errorEmptyList t = error $ "Data.Rope.Unpackable." ++ t ++ ": empty list"
− Data/Rope/Unpackable.hs
@@ -1,120 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-}-module Data.Rope.Unpackable- ( Unpackable(..)- ) where--import Prelude hiding (head, last, drop)-import qualified Prelude--import Data.Word (Word8)-import Data.Monoid (Monoid, mempty, mappend)-import qualified Data.Foldable as F--import qualified Data.FingerTree as F (empty, null, split)-import Data.FingerTree (FingerTree, ViewL(..),ViewR(..),viewl,viewr,(<|),(><))--import qualified Data.ByteString as S-import qualified Data.ByteString.Unsafe as S (unsafeTail, unsafeHead)-import qualified Data.ByteString.UTF8 as U-import qualified Data.ByteString.Lazy as L-import qualified Data.ByteString.Lazy.UTF8 as LU--import Data.Rope.Body (Count(..), Chunk(..), cons', snoc', measureBody) -- Chunk-import Data.Rope.Internal (Annotation(..), drop, Rope(..), body, toLazyByteString, uncons8, unsnoc8) -- Rope, etc.-import Codec.Binary.UTF8.Generic (UTF8Bytes)-import qualified Codec.Binary.UTF8.Generic as UTF8Bytes--class Unpackable a where- unpack :: Rope m -> [a]-- head :: Rope m -> a- head = Prelude.head . unpack-- last :: Rope m -> a-- uncons :: Annotation m => Rope m -> Maybe (a, Rope m)- unsnoc :: Annotation m => Rope m -> Maybe (Rope m, a)--newtype F = F { runF :: FingerTree Count Chunk } --instance Monoid F where- mempty = F F.empty- F a `mappend` F b = F (a >< b)--instance UTF8Bytes F Int where- bsplit 0 (F f) = (mempty, F f)- bsplit n (F f)- | n >= measureBody f = (F f, mempty)- | otherwise = (F (x `snoc'` y'), F (y'' `cons'` z))- where- (x, yz) = F.split (> Count n) f- Chunk y :< z = viewl yz- (y', y'') = S.splitAt (n - measureBody x) y- bdrop n = snd . UTF8Bytes.bsplit n- buncons f = case viewl (runF f) of- Chunk c :< cs -> Just (S.unsafeHead c, F (S.unsafeTail c `cons' ` cs))- EmptyL -> Nothing- tail (F f) = case viewl f of- Chunk c :< cs -> F (S.unsafeTail c `cons'`cs)- EmptyL -> errorEmptyList "tail"- elemIndex b = fmap fromIntegral . L.elemIndex b . L.fromChunks . map unchunk . F.toList . runF- pack = F . foldr (\l r -> Chunk l <| r) F.empty . L.toChunks . L.pack- empty = F F.empty- null = F.null . runF---- w2c :: Word8 -> Char--- w2c = unsafeChr . fromIntegral---instance Unpackable Word8 where- unpack = concatMap (S.unpack . unchunk) . F.toList . body- head (Rope t _) = case viewl t of- Chunk a :< _ -> S.head a- EmptyL -> errorEmptyList "head"- last (Rope t _) = case viewr t of- _ :> Chunk a -> S.last a- EmptyR -> errorEmptyList "last"- uncons = uncons8- unsnoc = unsnoc8--instance Unpackable Char where- unpack = LU.toString . toLazyByteString- head = Prelude.head . unpack- last = undefined -- TODO- uncons r@(Rope t _) = case UTF8Bytes.decode (F t) of - Nothing -> Nothing- Just (a,n) -> Just (a, drop n r)- unsnoc = undefined -- TODO--instance Unpackable S.ByteString where- unpack = map unchunk . F.toList . body- head r = case viewl (body r) of- Chunk a :< _ -> a- _ -> errorEmptyList "head"- last r = case viewr (body r) of- _ :> Chunk a -> a- _ -> errorEmptyList "last" - uncons r = case viewl (body r) of- Chunk a :< as -> Just (a, Rope as (drop' (S.length a) r))- EmptyL -> Nothing- unsnoc r = case viewr (body r) of- as :> Chunk a -> Just (Rope as (take' (measureBody as) r), a)- EmptyR -> Nothing--instance Unpackable Chunk where- unpack = F.toList . body- head r = case viewl (body r) of- a :< _ -> a- _ -> errorEmptyList "head"- last r = case viewr (body r) of- _ :> a -> a- _ -> errorEmptyList "last"- uncons r = case viewl (body r) of- Chunk a :< as -> Just (Chunk a, Rope as (drop' (S.length a) r))- EmptyL -> Nothing- unsnoc r = case viewr (body r) of- as :> Chunk a -> Just (Rope as (take' (measureBody as) r), Chunk a)- EmptyR -> Nothing--errorEmptyList :: String -> a-errorEmptyList t = error $ "Kata.Rope.Unpackable." ++ t ++ ": empty list"
− Data/Rope/Util/Bifunctor.hs
@@ -1,22 +0,0 @@-module Data.Rope.Util.Bifunctor (Bifunctor(..)) where--class Bifunctor f where- bimap :: (a -> b) -> (c -> d) -> f a c -> f b d- first :: (a -> b) -> f a c -> f b c- second :: (b -> c) -> f a b -> f a c- first f = bimap f id- second = bimap id- bimap f g = second g . first f--instance Bifunctor (,) where- bimap f g ~(a,b) = (f a, g b)- first f ~(a,b) = (f a, b)- second g ~(a,b) = (a, g b)- -instance Bifunctor Either where- bimap f _ (Left a) = Left (f a)- bimap _ g (Right b) = Right (g b)- first f (Left a) = Left (f a)- first _ (Right b) = Right b- second _ (Left a) = Left a- second g (Right b) = Right (g b)
− Data/Rope/Util/Comonad.hs
@@ -1,11 +0,0 @@-module Data.Rope.Util.Comonad - ( Comonad(..)- ) where--class Functor w => Comonad w where- extract :: w a -> a- duplicate :: w a -> w (w a)- extend :: (w a -> b) -> w a -> w b-- duplicate = extend id- extend f = fmap f . duplicate
− Data/Rope/Util/Coproduct.hs
@@ -1,84 +0,0 @@-{-# LANGUAGE TypeOperators #-}-module Data.Rope.Util.Coproduct- ( (:+:)(..)- , (:+)(..)- , Coproduct(..)- , counzip- ) where--import Control.Applicative-import Data.Rope.Util.Bifunctor--counzip :: (Coproduct s, Coproduct s', Functor f) => s (f a) (f b) -> f (s' a b)-counzip = fmap left ||| fmap right---- a coproduct that is strict in its left argument only-data a :+ b = Inl !a- | Inr b--instance Bifunctor (:+) where- first f (Inl a) = Inl (f a)- first _ (Inr b) = Inr b- second _ (Inl a) = Inl a- second g (Inr b) = Inr (g b)- bimap f _ (Inl a) = Inl (f a)- bimap _ g (Inr b) = Inr (g b)--instance Functor ((:+) a) where- fmap _ (Inl a) = Inl a- fmap g (Inr b) = Inr (g b)--instance Applicative ((:+) a) where- pure = Inr- Inl a <*> _ = Inl a- Inr _ <*> Inl a = Inl a- Inr f <*> Inr a = Inr (f a)- -instance Monad ((:+) a) where- return = Inr- Inl a >>= _ = Inl a- Inr a >>= f = f a--class Bifunctor s => Coproduct s where- left :: a -> s a b- right :: b -> s a b- (|||) :: (a -> c) -> (b -> c) -> s a b -> c- codiag :: s a a -> a--instance Coproduct Either where- left = Left- right = Right- (|||) = either- codiag (Left a) = a- codiag (Right a) = a--instance Coproduct (:+) where- left = Inl- right = Inr- (|||) f _ (Inl a) = f a- (|||) _ g (Inr b) = g b- codiag (Inl a) = a - codiag (Inr a) = a--data a :+: b = Left' !a - | Right' !b--instance Bifunctor (:+:) where- first f (Left' a) = Left' (f a)- first _ (Right' b) = Right' b- second _ (Left' a) = Left' a- second g (Right' b) = Right' (g b)- bimap f _ (Left' a) = Left' (f a)- bimap _ g (Right' b) = Right' (g b)--instance Functor ((:+:) a) where- fmap _ (Left' a) = Left' a- fmap g (Right' b) = Right' (g b)--instance Coproduct (:+:) where- left = Left'- right = Right'- (|||) f _ (Left' a) = f a- (|||) _ g (Right' b) = g b- codiag (Left' a) = a- codiag (Right' a) = a
− Data/Rope/Util/Product.hs
@@ -1,77 +0,0 @@-{-# LANGUAGE TypeOperators, FlexibleInstances, MultiParamTypeClasses #-}-module Data.Rope.Util.Product- ( (:*:)(..)- , Product(..), bothC- , unzip- ) where--import Data.Monoid hiding (Product(..))-import Data.Rope.Util.Comonad-import Data.Rope.Util.Bifunctor-import Data.Rope.Util.Reducer-import Prelude hiding (fst, snd, curry, uncurry, either, unzip)-import qualified Prelude as P---- a product that is strict in both arguments-data a :*: b = !a :*: !b--instance Bifunctor (:*:) where- first f (a :*: b) = f a :*: b- second f (a :*: b) = a :*: f b- bimap f g (a :*: b) = f a :*: g b--instance Functor ((:*:) a) where- fmap f (a :*: b) = a :*: f b--instance Comonad ((:*:) a) where- extract (_ :*: b) = b- extend f ab@(a :*: _) = a :*: f ab- duplicate ab@(a :*: _) = a :*: ab--instance (Monoid a, Monoid b) => Monoid (a :*: b) where- mempty = mempty :*: mempty- (a :*: b) `mappend` (c :*: d) = mappend a c :*: mappend b d--instance (Reducer c a, Reducer c b) => Reducer c (a :*: b) where- unit c = unit c :*: unit c- cons c (a :*: b) = cons c a :*: cons c b- snoc (a :*: b) c = snoc a c :*: snoc b c --class Bifunctor p => Product p where- fst :: p a b -> a- snd :: p a b -> b- pair :: a -> b -> p a b- curry :: (p a b -> c) -> a -> b -> c- uncurry :: (a -> b -> c) -> p a b -> c- both :: (a -> b) -> (a -> c) -> a -> p b c- diag :: a -> p a a-- diag = both id id- both f g = bimap f g . diag--instance Product (:*:) where- fst (a :*: _) = a- snd (_ :*: b) = b- pair = (:*:)- curry f a b = f (a :*: b)- uncurry f (a :*: b) = f a b- both f g a = f a :*: g a- diag a = a :*: a--instance Product (,) where- fst = P.fst- snd = P.snd- pair = (,)- curry = P.curry- uncurry = P.uncurry- both f g a = (f a, g a)- diag a = (a, a)--unzip :: (Product p, Functor f) => f (p a b) -> p (f a) (f b)-unzip = both (fmap fst) (fmap snd)-{-# INLINE unzip #-}---- CoKleisli (&&&)-bothC :: (Product p, Functor f) => (f a -> b) -> (f c -> d) -> f (p a c) -> p b d-bothC f g = both (f . fmap fst) (g . fmap snd)-{-# INLINE bothC #-}
Data/Rope/Util/Reducer.hs view
@@ -12,7 +12,7 @@ import Control.Applicative import Control.Monad import qualified Data.FingerTree as FingerTree-import Data.FingerTree (FingerTree, Measured, (><))+import Data.FingerTree (FingerTree, Measured) import Data.ByteString (ByteString) import qualified Data.ByteString.Lazy as Lazy
LICENSE view
@@ -1,1 +1,30 @@-All Rights Reserved+Copyright (c) 2010, Edward Kmett+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Isaac Jones nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
rope.cabal view
@@ -1,5 +1,5 @@ name: rope-version: 0.1+version: 0.2 license: BSD3 license-file: LICENSE author: Edward A. Kmett@@ -7,8 +7,8 @@ stability: experimental homepage: http://comonad.com/reader category: Language-synopsis: Tools for manipulating annotated ropes of bytestrings-description: Tools for manipulating annotated ropes of bytestrings+synopsis: Tools for manipulating fingertrees of bytestrings+description: Tools for manipulating fingertrees of bytestrings copyright: (c) 2010 Edward A. Kmett build-type: Simple cabal-version: >=1.2@@ -19,17 +19,11 @@ base >= 4 && < 6, bytestring >= 0.9.1.4 && < 0.10, fingertree >= 0.0.1 && < 0.1,- mtl >= 1.1 && < 1.2, utf8-string >= 0.3.5 && < 0.4 exposed-modules: Data.Rope Data.Rope.Body Data.Rope.Internal- Data.Rope.Unpackable- Data.Rope.Util.Bifunctor- Data.Rope.Util.Comonad- Data.Rope.Util.Coproduct- Data.Rope.Util.Product Data.Rope.Util.Reducer ghc-options: -Wall