monoid-subclasses 0.3.6.1 → 0.3.6.2
raw patch · 6 files changed
+565/−38 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Data.Monoid.Factorial: inits :: FactorialMonoid m => m -> [m]
+ Data.Monoid.Factorial: spanMaybe :: FactorialMonoid m => s -> (s -> m -> Maybe s) -> m -> (m, m, s)
+ Data.Monoid.Factorial: spanMaybe' :: FactorialMonoid m => s -> (s -> m -> Maybe s) -> m -> (m, m, s)
+ Data.Monoid.Factorial: tails :: FactorialMonoid m => m -> [m]
+ Data.Monoid.Textual: spanMaybe :: TextualMonoid t => s -> (s -> t -> Maybe s) -> (s -> Char -> Maybe s) -> t -> (t, t, s)
+ Data.Monoid.Textual: spanMaybe' :: TextualMonoid t => s -> (s -> t -> Maybe s) -> (s -> Char -> Maybe s) -> t -> (t, t, s)
- Data.Monoid.Factorial: break :: (FactorialMonoid m, FactorialMonoid m) => (m -> Bool) -> m -> (m, m)
+ Data.Monoid.Factorial: break :: FactorialMonoid m => (m -> Bool) -> m -> (m, m)
- Data.Monoid.Factorial: class MonoidNull m => FactorialMonoid m where factors = unfoldr splitPrimePrefix primePrefix = maybe mempty fst . splitPrimePrefix primeSuffix = maybe mempty snd . splitPrimeSuffix splitPrimePrefix x = case factors x of { [] -> Nothing prefix : rest -> Just (prefix, mconcat rest) } splitPrimeSuffix x = case factors x of { [] -> Nothing fs -> Just (mconcat (init fs), last fs) } foldl f f0 = foldl f f0 . factors foldl' f f0 = foldl' f f0 . factors foldr f f0 = foldr f f0 . factors length = length . factors foldMap f = foldr (mappend . f) mempty span p m = spanAfter id m where spanAfter f m = case splitPrimePrefix m of { Just (prime, rest) | p prime -> spanAfter (f . mappend prime) rest _ -> (f mempty, m) } break = span . (not .) split p m = prefix : splitRest where (prefix, rest) = break p m splitRest = case splitPrimePrefix rest of { Nothing -> [] Just (_, tail) -> split p tail } takeWhile p = fst . span p dropWhile p = snd . span p splitAt n m | n <= 0 = (mempty, m) | otherwise = split n id m where split 0 f m = (f mempty, m) split n f m = case splitPrimePrefix m of { Nothing -> (f mempty, m) Just (prime, rest) -> split (pred n) (f . mappend prime) rest } drop n p = snd (splitAt n p) take n p = fst (splitAt n p) reverse = mconcat . reverse . factors
+ Data.Monoid.Factorial: class MonoidNull m => FactorialMonoid m where factors = unfoldr splitPrimePrefix primePrefix = maybe mempty fst . splitPrimePrefix primeSuffix = maybe mempty snd . splitPrimeSuffix splitPrimePrefix x = case factors x of { [] -> Nothing prefix : rest -> Just (prefix, mconcat rest) } splitPrimeSuffix x = case factors x of { [] -> Nothing fs -> Just (mconcat (init fs), last fs) } inits = foldr (\ m l -> mempty : map (mappend m) l) [mempty] tails m = m : maybe [] (tails . snd) (splitPrimePrefix m) foldl f f0 = foldl f f0 . factors foldl' f f0 = foldl' f f0 . factors foldr f f0 = foldr f f0 . factors length = length . factors foldMap f = foldr (mappend . f) mempty span p m = spanAfter id m where spanAfter f m = case splitPrimePrefix m of { Just (prime, rest) | p prime -> spanAfter (f . mappend prime) rest _ -> (f mempty, m) } break = span . (not .) spanMaybe s0 f m0 = spanAfter id s0 m0 where spanAfter g s m = case splitPrimePrefix m of { Just (prime, rest) | Just s' <- f s prime -> spanAfter (g . mappend prime) s' rest | otherwise -> (g mempty, m, s) Nothing -> (m0, m, s) } spanMaybe' s0 f m0 = spanAfter id s0 m0 where spanAfter g s m = seq s $ case splitPrimePrefix m of { Just (prime, rest) | Just s' <- f s prime -> spanAfter (g . mappend prime) s' rest | otherwise -> (g mempty, m, s) Nothing -> (m0, m, s) } split p m = prefix : splitRest where (prefix, rest) = break p m splitRest = case splitPrimePrefix rest of { Nothing -> [] Just (_, tail) -> split p tail } takeWhile p = fst . span p dropWhile p = snd . span p splitAt n m | n <= 0 = (mempty, m) | otherwise = split n id m where split 0 f m = (f mempty, m) split n f m = case splitPrimePrefix m of { Nothing -> (f mempty, m) Just (prime, rest) -> split (pred n) (f . mappend prime) rest } drop n p = snd (splitAt n p) take n p = fst (splitAt n p) reverse = mconcat . reverse . factors
- Data.Monoid.Factorial: drop :: (FactorialMonoid m, FactorialMonoid m) => Int -> m -> m
+ Data.Monoid.Factorial: drop :: FactorialMonoid m => Int -> m -> m
- Data.Monoid.Factorial: dropWhile :: (FactorialMonoid m, FactorialMonoid m) => (m -> Bool) -> m -> m
+ Data.Monoid.Factorial: dropWhile :: FactorialMonoid m => (m -> Bool) -> m -> m
- Data.Monoid.Factorial: foldMap :: (FactorialMonoid m, FactorialMonoid m, Monoid n) => (m -> n) -> m -> n
+ Data.Monoid.Factorial: foldMap :: (FactorialMonoid m, Monoid n) => (m -> n) -> m -> n
- Data.Monoid.Factorial: reverse :: (FactorialMonoid m, FactorialMonoid m) => m -> m
+ Data.Monoid.Factorial: reverse :: FactorialMonoid m => m -> m
- Data.Monoid.Factorial: take :: (FactorialMonoid m, FactorialMonoid m) => Int -> m -> m
+ Data.Monoid.Factorial: take :: FactorialMonoid m => Int -> m -> m
- Data.Monoid.Factorial: takeWhile :: (FactorialMonoid m, FactorialMonoid m) => (m -> Bool) -> m -> m
+ Data.Monoid.Factorial: takeWhile :: FactorialMonoid m => (m -> Bool) -> m -> m
- Data.Monoid.Textual: class (IsString t, LeftReductiveMonoid t, LeftGCDMonoid t, FactorialMonoid t) => TextualMonoid t where fromText = fromString . unpack singleton = fromString . (: []) characterPrefix = fmap fst . splitCharacterPrefix map f = concatMap (singleton . f) concatMap f = foldr mappend (mappend . f) mempty all p = foldr (const id) ((&&) . p) True any p = foldr (const id) ((||) . p) False foldl ft fc = foldl (\ a prime -> maybe (ft a prime) (fc a) (characterPrefix prime)) foldr ft fc = foldr (\ prime -> maybe (ft prime) fc (characterPrefix prime)) foldl' ft fc = foldl' (\ a prime -> maybe (ft a prime) (fc a) (characterPrefix prime)) scanl f c = mappend (singleton c) . fst . foldl foldlOther (foldlChars f) (mempty, c) scanl1 f t = case (splitPrimePrefix t, splitCharacterPrefix t) of { (Nothing, _) -> t (Just (prefix, suffix), Nothing) -> mappend prefix (scanl1 f suffix) (Just _, Just (c, suffix)) -> scanl f c suffix } scanr f c = fst . foldr foldrOther (foldrChars f) (singleton c, c) scanr1 f = fst . foldr foldrOther fc (mempty, Nothing) where fc c (t, Nothing) = (mappend (singleton c) t, Just c) fc c1 (t, Just c2) = (mappend (singleton c') t, Just c') where c' = f c1 c2 mapAccumL f a0 = foldl ft fc (a0, mempty) where ft (a, t1) t2 = (a, mappend t1 t2) fc (a, t) c = (a', mappend t (singleton c')) where (a', c') = f a c mapAccumR f a0 = foldr ft fc (a0, mempty) where ft t1 (a, t2) = (a, mappend t1 t2) fc c (a, t) = (a', mappend (singleton c') t) where (a', c') = f a c takeWhile pt pc = fst . span pt pc dropWhile pt pc = snd . span pt pc span pt pc = span (\ prime -> maybe (pt prime) pc (characterPrefix prime)) break pt pc = break (\ prime -> maybe (pt prime) pc (characterPrefix prime)) split p m = prefix : splitRest where (prefix, rest) = break (const False) p m splitRest = case splitCharacterPrefix rest of { Nothing -> [] Just (_, tail) -> split p tail } find p = foldr (const id) (\ c r -> if p c then Just c else r) Nothing
+ Data.Monoid.Textual: class (IsString t, LeftReductiveMonoid t, LeftGCDMonoid t, FactorialMonoid t) => TextualMonoid t where fromText = fromString . unpack singleton = fromString . (: []) characterPrefix = fmap fst . splitCharacterPrefix map f = concatMap (singleton . f) concatMap f = foldr mappend (mappend . f) mempty all p = foldr (const id) ((&&) . p) True any p = foldr (const id) ((||) . p) False foldl ft fc = foldl (\ a prime -> maybe (ft a prime) (fc a) (characterPrefix prime)) foldr ft fc = foldr (\ prime -> maybe (ft prime) fc (characterPrefix prime)) foldl' ft fc = foldl' (\ a prime -> maybe (ft a prime) (fc a) (characterPrefix prime)) scanl f c = mappend (singleton c) . fst . foldl foldlOther (foldlChars f) (mempty, c) scanl1 f t = case (splitPrimePrefix t, splitCharacterPrefix t) of { (Nothing, _) -> t (Just (prefix, suffix), Nothing) -> mappend prefix (scanl1 f suffix) (Just _, Just (c, suffix)) -> scanl f c suffix } scanr f c = fst . foldr foldrOther (foldrChars f) (singleton c, c) scanr1 f = fst . foldr foldrOther fc (mempty, Nothing) where fc c (t, Nothing) = (mappend (singleton c) t, Just c) fc c1 (t, Just c2) = (mappend (singleton c') t, Just c') where c' = f c1 c2 mapAccumL f a0 = foldl ft fc (a0, mempty) where ft (a, t1) t2 = (a, mappend t1 t2) fc (a, t) c = (a', mappend t (singleton c')) where (a', c') = f a c mapAccumR f a0 = foldr ft fc (a0, mempty) where ft t1 (a, t2) = (a, mappend t1 t2) fc c (a, t) = (a', mappend (singleton c') t) where (a', c') = f a c takeWhile pt pc = fst . span pt pc dropWhile pt pc = snd . span pt pc span pt pc = span (\ prime -> maybe (pt prime) pc (characterPrefix prime)) break pt pc = break (\ prime -> maybe (pt prime) pc (characterPrefix prime)) spanMaybe s0 ft fc t0 = spanAfter id s0 t0 where spanAfter g s t = case splitPrimePrefix t of { Just (prime, rest) | Just s' <- maybe (ft s prime) (fc s) (characterPrefix prime) -> spanAfter (g . mappend prime) s' rest | otherwise -> (g mempty, t, s) Nothing -> (t0, t, s) } spanMaybe' s0 ft fc t0 = spanAfter id s0 t0 where spanAfter g s t = seq s $ case splitPrimePrefix t of { Just (prime, rest) | Just s' <- maybe (ft s prime) (fc s) (characterPrefix prime) -> spanAfter (g . mappend prime) s' rest | otherwise -> (g mempty, t, s) Nothing -> (t0, t, s) } split p m = prefix : splitRest where (prefix, rest) = break (const False) p m splitRest = case splitCharacterPrefix rest of { Nothing -> [] Just (_, tail) -> split p tail } find p = foldr (const id) (\ c r -> if p c then Just c else r) Nothing
Files
- Data/Monoid/Factorial.hs +130/−9
- Data/Monoid/Instances/ByteString/UTF8.hs +203/−23
- Data/Monoid/Null.hs +4/−0
- Data/Monoid/Textual.hs +203/−1
- Test/TestMonoidSubclasses.hs +23/−3
- monoid-subclasses.cabal +2/−2
Data/Monoid/Factorial.hs view
@@ -1,5 +1,5 @@ {- - Copyright 2011-2013 Mario Blazevic+ Copyright 2011-2014 Mario Blazevic License: BSD3 (see BSD3-LICENSE.txt file) -}@@ -35,6 +35,8 @@ import qualified Data.Sequence as Sequence import qualified Data.Set as Set import qualified Data.Vector as Vector+import Data.Int (Int64)+import Data.Word (Word8) import Data.Numbers.Primes (primeFactors) import Data.Monoid.Null (MonoidNull(null), PositiveMonoid)@@ -57,6 +59,8 @@ -- > reverse == mconcat . List.reverse . factors -- > primePrefix == maybe mempty fst . splitPrimePrefix -- > primeSuffix == maybe mempty snd . splitPrimeSuffix+-- > inits == List.map mconcat . List.tails . factors+-- > tails == List.map mconcat . List.tails . factors -- > foldl f a == List.foldl f a . factors -- > foldl' f a == List.foldl' f a . factors -- > foldr f a == List.foldr f a . factors@@ -64,6 +68,15 @@ -- > List.all (List.all (not . pred) . factors) . split pred -- > mconcat . intersperse prime . split (== prime) == id -- > splitAt i m == (mconcat l, mconcat r) where (l, r) = List.splitAt i (factors m)+-- > spanMaybe () (const $ bool Nothing (Maybe ()) . p) m == (takeWhile p m, dropWhile p m, ())+-- > spanMaybe s0 (\s m-> Just $ f s m) m0 == (m0, mempty, foldl f s0 m0)+-- > let (prefix, suffix, s') = spanMaybe s f m+-- > foldMaybe = foldl g (Just s)+-- > g s m = s >>= flip f m+-- > in all ((Nothing ==) . foldMaybe) (inits prefix)+-- > && prefix == last (filter (isJust . foldMaybe) $ inits m)+-- > && Just s' == foldMaybe prefix+-- > && m == prefix <> suffix -- -- A minimal instance definition must implement 'factors' or 'splitPrimePrefix'. Other methods are provided and should -- be implemented only for performance reasons.@@ -78,6 +91,10 @@ splitPrimePrefix :: m -> Maybe (m, m) -- | Splits the argument into its prime suffix and the remaining prefix. Returns 'Nothing' for 'mempty'. splitPrimeSuffix :: m -> Maybe (m, m)+ -- | Returns the list of all prefixes of the argument, 'mempty' first.+ inits :: m -> [m]+ -- | Returns the list of all suffixes of the argument, 'mempty' last.+ tails :: m -> [m] -- | Like 'List.foldl' from "Data.List" on the list of 'primes'. foldl :: (a -> m -> a) -> a -> m -> a -- | Like 'List.foldl'' from "Data.List" on the list of 'primes'.@@ -88,26 +105,30 @@ length :: m -> Int -- | Generalizes 'foldMap' from "Data.Foldable", except the function arguments are prime factors rather than the -- structure elements.- foldMap :: (FactorialMonoid m, Monoid n) => (m -> n) -> m -> n+ foldMap :: Monoid n => (m -> n) -> m -> n -- | Like 'List.span' from "Data.List" on the list of 'primes'. span :: (m -> Bool) -> m -> (m, m) -- | Equivalent to 'List.break' from "Data.List".- break :: FactorialMonoid m => (m -> Bool) -> m -> (m, m)+ break :: (m -> Bool) -> m -> (m, m) -- | Splits the monoid into components delimited by prime separators satisfying the given predicate. The primes -- satisfying the predicate are not a part of the result. split :: (m -> Bool) -> m -> [m] -- | Equivalent to 'List.takeWhile' from "Data.List".- takeWhile :: FactorialMonoid m => (m -> Bool) -> m -> m+ takeWhile :: (m -> Bool) -> m -> m -- | Equivalent to 'List.dropWhile' from "Data.List".- dropWhile :: FactorialMonoid m => (m -> Bool) -> m -> m+ dropWhile :: (m -> Bool) -> m -> m+ -- | A stateful variant of 'span', threading the result of the test function as long as it returns 'Just'.+ spanMaybe :: s -> (s -> m -> Maybe s) -> m -> (m, m, s)+ -- | Strict version of 'spanMaybe'.+ spanMaybe' :: s -> (s -> m -> Maybe s) -> m -> (m, m, s) -- | Like 'List.splitAt' from "Data.List" on the list of 'primes'. splitAt :: Int -> m -> (m, m) -- | Equivalent to 'List.drop' from "Data.List".- drop :: FactorialMonoid m => Int -> m -> m+ drop :: Int -> m -> m -- | Equivalent to 'List.take' from "Data.List".- take :: FactorialMonoid m => Int -> m -> m+ take :: Int -> m -> m -- | Equivalent to 'List.reverse' from "Data.List".- reverse :: FactorialMonoid m => m -> m+ reverse :: m -> m factors = List.unfoldr splitPrimePrefix primePrefix = maybe mempty fst . splitPrimePrefix@@ -118,6 +139,8 @@ splitPrimeSuffix x = case factors x of [] -> Nothing fs -> Just (mconcat (List.init fs), List.last fs)+ inits = foldr (\m l-> mempty : List.map (mappend m) l) [mempty]+ tails m = m : maybe [] (tails . snd) (splitPrimePrefix m) foldl f f0 = List.foldl f f0 . factors foldl' f f0 = List.foldl' f f0 . factors foldr f f0 = List.foldr f f0 . factors@@ -128,6 +151,17 @@ of Just (prime, rest) | p prime -> spanAfter (f . mappend prime) rest _ -> (f mempty, m) break = span . (not .)+ spanMaybe s0 f m0 = spanAfter id s0 m0+ where spanAfter g s m = case splitPrimePrefix m+ of Just (prime, rest) | Just s' <- f s prime -> spanAfter (g . mappend prime) s' rest+ | otherwise -> (g mempty, m, s)+ Nothing -> (m0, m, s)+ spanMaybe' s0 f m0 = spanAfter id s0 m0+ where spanAfter g s m = seq s $+ case splitPrimePrefix m+ of Just (prime, rest) | Just s' <- f s prime -> spanAfter (g . mappend prime) s' rest+ | otherwise -> (g mempty, m, s)+ Nothing -> (m0, m, s) split p m = prefix : splitRest where (prefix, rest) = break p m splitRest = case splitPrimePrefix rest@@ -171,6 +205,8 @@ splitPrimeSuffix (Dual a) = case splitPrimePrefix a of Nothing -> Nothing Just (p, s) -> Just (Dual s, Dual p)+ inits (Dual a) = fmap Dual (reverse $ tails a)+ tails (Dual a) = fmap Dual (reverse $ inits a) reverse (Dual a) = Dual (reverse a) instance (Integral a, Eq a) => FactorialMonoid (Sum a) where@@ -210,6 +246,8 @@ of (_, Just (bp, bs)) -> Just ((a, bp), (mempty, bs)) (Just (ap, as), Nothing) -> Just ((ap, b), (as, b)) (Nothing, Nothing) -> Nothing+ inits (a, b) = List.map (flip (,) mempty) (inits a) ++ List.map ((,) a) (List.tail $ inits b)+ tails (a, b) = List.map (flip (,) b) (tails a) ++ List.map ((,) mempty) (List.tail $ tails b) foldl f a (x, y) = foldl f2 (foldl f1 a x) y where f1 a = f a . fromFst f2 a = f a . fromSnd@@ -224,6 +262,14 @@ where (xp, xs) = span (p . fromFst) x (yp, ys) | null xs = span (p . fromSnd) y | otherwise = (mempty, y)+ spanMaybe s0 f (x, y) | null xs = ((xp, yp), (xs, ys), s2)+ | otherwise = ((xp, mempty), (xs, y), s1)+ where (xp, xs, s1) = spanMaybe s0 (\s-> f s . fromFst) x+ (yp, ys, s2) = spanMaybe s1 (\s-> f s . fromSnd) y+ spanMaybe' s0 f (x, y) | null xs = ((xp, yp), (xs, ys), s2)+ | otherwise = ((xp, mempty), (xs, y), s1)+ where (xp, xs, s1) = spanMaybe' s0 (\s-> f s . fromFst) x+ (yp, ys, s2) = spanMaybe' s1 (\s-> f s . fromSnd) y split p (x, y) = fst $ List.foldr combine (ys, False) xs where xs = List.map fromFst $ split (p . fromFst) x ys = List.map fromSnd $ split (p . fromSnd) y@@ -255,6 +301,8 @@ splitPrimeSuffix xs = Just (split id xs) where split f last@[x] = (f [], last) split f (x:xs) = split (f . (x:)) xs+ inits = List.inits+ tails = List.tails foldl _ a [] = a foldl f a (x:xs) = foldl f (f a [x]) xs foldl' _ a [] = a@@ -267,6 +315,14 @@ span f = List.span (f . (:[])) dropWhile f = List.dropWhile (f . (:[])) takeWhile f = List.takeWhile (f . (:[]))+ spanMaybe s0 f l = (prefix' [], suffix' [], s')+ where (prefix', suffix', s', live') = List.foldl' g (id, id, s0, True) l+ g (prefix, suffix, s, live) x | live, Just s' <- f s [x] = (prefix . (x:), id, s', True)+ | otherwise = (prefix, suffix . (x:), s, False)+ spanMaybe' s0 f l = (prefix' [], suffix' [], s')+ where (prefix', suffix', s', live') = List.foldl' g (id, id, s0, True) l+ g (prefix, suffix, s, live) x | live, Just s' <- f s [x] = seq s' $ (prefix . (x:), id, s', True)+ | otherwise = (prefix, suffix . (x:), s, False) splitAt = List.splitAt drop = List.drop take = List.take@@ -281,6 +337,8 @@ primeSuffix x = ByteString.drop (ByteString.length x - 1) x splitPrimePrefix x = if ByteString.null x then Nothing else Just (ByteString.splitAt 1 x) splitPrimeSuffix x = if ByteString.null x then Nothing else Just (ByteString.splitAt (ByteString.length x - 1) x)+ inits = ByteString.inits+ tails = ByteString.tails foldl f = ByteString.foldl f' where f' a byte = f a (ByteString.singleton byte) foldl' f = ByteString.foldl' f'@@ -288,6 +346,14 @@ foldr f = ByteString.foldr (f . ByteString.singleton) break f = ByteString.break (f . ByteString.singleton) span f = ByteString.span (f . ByteString.singleton)+ spanMaybe s0 f b = case ByteString.foldr g id b (0, s0)+ of (i, s') | (prefix, suffix) <- ByteString.splitAt i b -> (prefix, suffix, s')+ where g w cont (i, s) | Just s' <- f s (ByteString.singleton w) = let i' = succ i :: Int in seq i' $ cont (i', s')+ | otherwise = (i, s)+ spanMaybe' s0 f b = case ByteString.foldr g id b (0, s0)+ of (i, s') | (prefix, suffix) <- ByteString.splitAt i b -> (prefix, suffix, s')+ where g w cont (i, s) | Just s' <- f s (ByteString.singleton w) = let i' = succ i :: Int in seq i' $ seq s' $ cont (i', s')+ | otherwise = (i, s) dropWhile f = ByteString.dropWhile (f . ByteString.singleton) takeWhile f = ByteString.takeWhile (f . ByteString.singleton) length = ByteString.length@@ -309,6 +375,8 @@ else Just (LazyByteString.splitAt 1 x) splitPrimeSuffix x = if LazyByteString.null x then Nothing else Just (LazyByteString.splitAt (LazyByteString.length x - 1) x)+ inits = LazyByteString.inits+ tails = LazyByteString.tails foldl f = LazyByteString.foldl f' where f' a byte = f a (LazyByteString.singleton byte) foldl' f = LazyByteString.foldl' f'@@ -318,6 +386,15 @@ length = fromIntegral . LazyByteString.length break f = LazyByteString.break (f . LazyByteString.singleton) span f = LazyByteString.span (f . LazyByteString.singleton)+ spanMaybe s0 f b = case LazyByteString.foldr g id b (0, s0)+ of (i, s') | (prefix, suffix) <- LazyByteString.splitAt i b -> (prefix, suffix, s')+ where g w cont (i, s) | Just s' <- f s (LazyByteString.singleton w) = let i' = succ i :: Int64 in seq i' $ cont (i', s')+ | otherwise = (i, s)+ spanMaybe' s0 f b = case LazyByteString.foldr g id b (0, s0)+ of (i, s') | (prefix, suffix) <- LazyByteString.splitAt i b -> (prefix, suffix, s')+ where g w cont (i, s)+ | Just s' <- f s (LazyByteString.singleton w) = let i' = succ i :: Int64 in seq i' $ seq s' $ cont (i', s')+ | otherwise = (i, s) dropWhile f = LazyByteString.dropWhile (f . LazyByteString.singleton) takeWhile f = LazyByteString.takeWhile (f . LazyByteString.singleton) split f = LazyByteString.splitWith f'@@ -333,6 +410,8 @@ primeSuffix x = if Text.null x then Text.empty else Text.singleton (Text.last x) splitPrimePrefix = fmap (first Text.singleton) . Text.uncons splitPrimeSuffix x = if Text.null x then Nothing else Just (Text.init x, Text.singleton (Text.last x))+ inits = Text.inits+ tails = Text.tails foldl f = Text.foldl f' where f' a char = f a (Text.singleton char) foldl' f = Text.foldl' f'@@ -344,6 +423,14 @@ break f = Text.break (f . Text.singleton) dropWhile f = Text.dropWhile (f . Text.singleton) takeWhile f = Text.takeWhile (f . Text.singleton)+ spanMaybe s0 f t = case Text.foldr g id t (0, s0)+ of (i, s') | (prefix, suffix) <- Text.splitAt i t -> (prefix, suffix, s')+ where g c cont (i, s) | Just s' <- f s (Text.singleton c) = let i' = succ i :: Int in seq i' $ cont (i', s')+ | otherwise = (i, s)+ spanMaybe' s0 f t = case Text.foldr g id t (0, s0)+ of (i, s') | (prefix, suffix) <- Text.splitAt i t -> (prefix, suffix, s')+ where g c cont (i, s) | Just s' <- f s (Text.singleton c) = let i' = succ i :: Int in seq i' $ seq s' $ cont (i', s')+ | otherwise = (i, s) split f = Text.split f' where f' = f . Text.singleton splitAt = Text.splitAt@@ -359,6 +446,8 @@ splitPrimeSuffix x = if LazyText.null x then Nothing else Just (LazyText.init x, LazyText.singleton (LazyText.last x))+ inits = LazyText.inits+ tails = LazyText.tails foldl f = LazyText.foldl f' where f' a char = f a (LazyText.singleton char) foldl' f = LazyText.foldl' f'@@ -370,6 +459,14 @@ break f = LazyText.break (f . LazyText.singleton) dropWhile f = LazyText.dropWhile (f . LazyText.singleton) takeWhile f = LazyText.takeWhile (f . LazyText.singleton)+ spanMaybe s0 f t = case LazyText.foldr g id t (0, s0)+ of (i, s') | (prefix, suffix) <- LazyText.splitAt i t -> (prefix, suffix, s')+ where g c cont (i, s) | Just s' <- f s (LazyText.singleton c) = let i' = succ i :: Int64 in seq i' $ cont (i', s')+ | otherwise = (i, s)+ spanMaybe' s0 f t = case LazyText.foldr g id t (0, s0)+ of (i, s') | (prefix, suffix) <- LazyText.splitAt i t -> (prefix, suffix, s')+ where g c cont (i, s) | Just s' <- f s (LazyText.singleton c) = let i' = succ i :: Int64 in seq i' $ seq s' $ cont (i', s')+ | otherwise = (i, s) split f = LazyText.split f' where f' = f . LazyText.singleton splitAt = LazyText.splitAt . fromIntegral@@ -444,6 +541,8 @@ splitPrimeSuffix seq = case Sequence.viewr seq of Sequence.EmptyR -> Nothing rest Sequence.:> last -> Just (rest, Sequence.singleton last)+ inits = Foldable.toList . Sequence.inits+ tails = Foldable.toList . Sequence.tails foldl f = Foldable.foldl f' where f' a b = f a (Sequence.singleton b) foldl' f = Foldable.foldl' f'@@ -454,6 +553,14 @@ break f = Sequence.breakl (f . Sequence.singleton) dropWhile f = Sequence.dropWhileL (f . Sequence.singleton) takeWhile f = Sequence.takeWhileL (f . Sequence.singleton)+ spanMaybe s0 f b = case Foldable.foldr g id b (0, s0)+ of (i, s') | (prefix, suffix) <- Sequence.splitAt i b -> (prefix, suffix, s')+ where g x cont (i, s) | Just s' <- f s (Sequence.singleton x) = let i' = succ i :: Int in seq i' $ cont (i', s')+ | otherwise = (i, s)+ spanMaybe' s0 f b = case Foldable.foldr g id b (0, s0)+ of (i, s') | (prefix, suffix) <- Sequence.splitAt i b -> (prefix, suffix, s')+ where g x cont (i, s) | Just s' <- f s (Sequence.singleton x) = let i' = succ i :: Int in seq i' $ seq s' $ cont (i', s')+ | otherwise = (i, s) splitAt = Sequence.splitAt drop = Sequence.drop take = Sequence.take@@ -483,11 +590,15 @@ factors x = factorize (Vector.length x) x where factorize 0 xs = [] factorize n xs = x : factorize (pred n) xs'- where (x, xs') = Vector.splitAt 1 xs+ where (x, xs') = Vector.splitAt 1 xs primePrefix = Vector.take 1 primeSuffix x = Vector.drop (Vector.length x - 1) x splitPrimePrefix x = if Vector.null x then Nothing else Just (Vector.splitAt 1 x) splitPrimeSuffix x = if Vector.null x then Nothing else Just (Vector.splitAt (Vector.length x - 1) x)+ inits x = initsWith x []+ where initsWith x rest | Vector.null x = x:rest+ | otherwise = initsWith (Vector.unsafeInit x) (x:rest)+ tails x = x : if Vector.null x then [] else tails (Vector.unsafeTail x) foldl f = Vector.foldl f' where f' a byte = f a (Vector.singleton byte) foldl' f = Vector.foldl' f'@@ -498,6 +609,16 @@ span f = Vector.span (f . Vector.singleton) dropWhile f = Vector.dropWhile (f . Vector.singleton) takeWhile f = Vector.takeWhile (f . Vector.singleton)+ spanMaybe s0 f v = case Vector.ifoldr g Left v s0+ of Left s' -> (v, Vector.empty, s')+ Right (i, s') | (prefix, suffix) <- Vector.splitAt i v -> (prefix, suffix, s')+ where g i x cont s | Just s' <- f s (Vector.singleton x) = cont s'+ | otherwise = Right (i, s)+ spanMaybe' s0 f v = case Vector.ifoldr' g Left v s0+ of Left s' -> (v, Vector.empty, s')+ Right (i, s') | (prefix, suffix) <- Vector.splitAt i v -> (prefix, suffix, s')+ where g i x cont s | Just s' <- f s (Vector.singleton x) = seq s' (cont s')+ | otherwise = Right (i, s) splitAt = Vector.splitAt drop = Vector.drop take = Vector.take
Data/Monoid/Instances/ByteString/UTF8.hs view
@@ -8,6 +8,8 @@ -- instance. -- +{-# LANGUAGE Haskell2010 #-}+ module Data.Monoid.Instances.ByteString.UTF8 ( ByteStringUTF8(..), decode )@@ -16,19 +18,22 @@ import Prelude hiding (drop, dropWhile, foldl, foldl1, foldr, foldr1, scanl, scanr, scanl1, scanr1, map, concatMap, break, span) +import Control.Exception (assert) import Data.Bits ((.&.), (.|.), shiftL, shiftR) import Data.Char (chr, ord) import qualified Data.Foldable as Foldable import qualified Data.List as List-import Data.Maybe (fromMaybe)+import Data.Functor ((<$>))+import Data.Maybe (fromJust, fromMaybe) import Data.String (IsString(fromString)) import Data.Word (Word8) import Data.ByteString (ByteString) import qualified Data.ByteString as ByteString import qualified Data.ByteString.Char8 as ByteString.Char8-import Data.ByteString.Unsafe (unsafeDrop, unsafeHead, unsafeTail, unsafeIndex)+import Data.ByteString.Internal (w2c)+import Data.ByteString.Unsafe (unsafeDrop, unsafeHead, unsafeTail, unsafeTake, unsafeIndex) -import Data.Monoid (Monoid(mempty, mappend))+import Data.Monoid (Monoid(mempty, mappend), (<>)) import Data.Monoid.Cancellative (LeftReductiveMonoid(..), LeftCancellativeMonoid, LeftGCDMonoid(..)) import Data.Monoid.Null (MonoidNull(null), PositiveMonoid) import Data.Monoid.Factorial (FactorialMonoid(..))@@ -54,20 +59,27 @@ instance Monoid ByteStringUTF8 where mempty = ByteStringUTF8 ByteString.empty+ {-# INLINE mempty #-} ByteStringUTF8 a `mappend` ByteStringUTF8 b = ByteStringUTF8 (a `mappend` b)+ {-# INLINE mappend #-} instance MonoidNull ByteStringUTF8 where null (ByteStringUTF8 b) = ByteString.null b+ {-# INLINE null #-} instance LeftReductiveMonoid ByteStringUTF8 where stripPrefix (ByteStringUTF8 a) (ByteStringUTF8 b) = fmap ByteStringUTF8 (stripPrefix a b)+ {-# INLINE stripPrefix #-} ByteStringUTF8 a `isPrefixOf` ByteStringUTF8 b = a `isPrefixOf` b+ {-# INLINE isPrefixOf #-} instance LeftCancellativeMonoid ByteStringUTF8 instance LeftGCDMonoid ByteStringUTF8 where commonPrefix (ByteStringUTF8 a) (ByteStringUTF8 b) = ByteStringUTF8 (commonPrefix a b)+ {-# INLINE commonPrefix #-} stripCommonPrefix (ByteStringUTF8 a) (ByteStringUTF8 b) = wrapTriple (stripCommonPrefix a b)+ {-# INLINE stripCommonPrefix #-} instance Show ByteStringUTF8 where showsPrec _ bs s = '"' : Textual.foldr showsBytes (:) ('"' : s) bs@@ -75,6 +87,7 @@ instance IsString ByteStringUTF8 where fromString = ByteStringUTF8 . Foldable.foldMap fromChar+ {-# INLINE fromString #-} instance PositiveMonoid ByteStringUTF8 @@ -85,39 +98,50 @@ | otherwise = case ByteString.findIndex byteStartsCharacter (unsafeTail bs) of Just i -> Just (wrapPair $ ByteString.splitAt (succ i) bs) Nothing -> Just (utf8, ByteStringUTF8 $ ByteString.empty)+ {-# INLINABLE splitPrimePrefix #-} splitPrimeSuffix utf8@(ByteStringUTF8 bs) | ByteString.null bs = Nothing | ByteString.null prefix = Just (wrapPair split) | not (ByteString.null suffix) && ByteString.last prefix < 0x80 = Just (wrapPair split) | otherwise = Just (wrapPair $ ByteString.splitAt (pred $ ByteString.length prefix) bs) where split@(prefix, suffix) = ByteString.breakEnd byteStartsCharacter bs+ {-# INLINABLE splitPrimeSuffix #-} primePrefix utf8@(ByteStringUTF8 bs) | ByteString.null bs = utf8 | unsafeHead bs < 0x80 = ByteStringUTF8 (ByteString.take 1 bs) | otherwise = case ByteString.findIndex byteStartsCharacter (unsafeTail bs) of Just i -> ByteStringUTF8 (ByteString.take (succ i) bs) Nothing -> utf8+ {-# INLINABLE primePrefix #-} factors (ByteStringUTF8 bs) = List.map ByteStringUTF8 $ ByteString.groupBy continued bs where continued a b = a >= 0x80 && b >= 0x80 && b < 0xC0+ {-# INLINABLE factors #-} length (ByteStringUTF8 bs) = fst (ByteString.foldl' count (0, False) bs) where count (n, high) byte | byte < 0x80 = (succ n, False) | byte < 0xC0 = (if high then n else succ n, True) | otherwise = (succ n, True)+ {-# INLINABLE length #-} foldl f a0 (ByteStringUTF8 bs) = List.foldl f' a0 (groupASCII bs) where f' a b | unsafeHead b < 0x80 = ByteString.foldl f'' a b | otherwise = f a (ByteStringUTF8 b) f'' a w = f a (ByteStringUTF8 $ ByteString.singleton w)+ {-# INLINABLE foldl #-} foldl' f a0 (ByteStringUTF8 bs) = List.foldl' f' a0 (groupASCII bs) where f' a b | unsafeHead b < 0x80 = ByteString.foldl' f'' a b | otherwise = f a (ByteStringUTF8 b) f'' a w = f a (ByteStringUTF8 $ ByteString.singleton w)+ {-# INLINABLE foldl' #-} foldr f a0 (ByteStringUTF8 bs) = List.foldr f' a0 (groupASCII bs) where f' b a | unsafeHead b < 0x80 = ByteString.foldr f'' a b | otherwise = f (ByteStringUTF8 b) a f'' w a = f (ByteStringUTF8 $ ByteString.singleton w) a+ {-# INLINABLE foldr #-} splitAt n (ByteStringUTF8 bs) = wrapPair (ByteString.splitAt (charStartIndex n bs) bs)+ {-# INLINE splitAt #-} take n (ByteStringUTF8 bs) = ByteStringUTF8 (ByteString.take (charStartIndex n bs) bs)+ {-# INLINE take #-} drop n (ByteStringUTF8 bs) = ByteStringUTF8 (ByteString.drop (charStartIndex n bs) bs)+ {-# INLINE drop #-} dropWhile p (ByteStringUTF8 bs) = dropASCII bs where dropASCII bs = let suffix = ByteString.dropWhile (\w-> w < 0x80 && p (ByteStringUTF8 $ ByteString.singleton w)) bs@@ -132,36 +156,107 @@ in if p (ByteStringUTF8 hd) then dropASCII tl else utf8+ {-# INLINE dropWhile #-} takeWhile p utf8@(ByteStringUTF8 bs) = ByteStringUTF8 $ ByteString.take (ByteString.length bs - ByteString.length s) bs where suffix@(ByteStringUTF8 s) = Factorial.dropWhile p utf8+ {-# INLINE takeWhile #-} span p utf8@(ByteStringUTF8 bs) = (ByteStringUTF8 $ ByteString.take (ByteString.length bs - ByteString.length s) bs, suffix) where suffix@(ByteStringUTF8 s) = Factorial.dropWhile p utf8+ {-# INLINE span #-} break p = Factorial.span (not . p)+ {-# INLINE break #-}+ spanMaybe s0 f (ByteStringUTF8 bs) = (ByteStringUTF8 $ ByteString.take (ByteString.length bs - ByteString.length dropped) bs,+ ByteStringUTF8 dropped,+ s')+ where (dropped, s') = dropASCII s0 bs+ dropASCII s bs =+ let suffix = ByteString.drop index bs+ (index, s') = ByteString.foldr f8 id bs (0, s)+ f8 w cont (i, s)+ | w < 0x80, Just s' <- f s (ByteStringUTF8 $ ByteString.singleton w) =+ let i' = succ i :: Int in seq i' $ cont (i', s')+ | otherwise = (i, s)+ in if ByteString.null suffix || unsafeHead suffix < 0x80+ then (suffix, s')+ else dropMultiByte s' suffix+ dropMultiByte s bs =+ case ByteString.findIndex byteStartsCharacter (unsafeTail bs)+ of Nothing -> case f s (ByteStringUTF8 bs)+ of Just s' -> (ByteString.empty, s')+ Nothing -> (bs, s)+ Just i -> let (hd, tl) = ByteString.splitAt (succ i) bs+ in case f s (ByteStringUTF8 hd)+ of Just s' -> dropASCII s' tl+ Nothing -> (bs, s)+ {-# INLINE spanMaybe #-}+ spanMaybe' s0 f (ByteStringUTF8 bs) = (ByteStringUTF8 $ ByteString.take (ByteString.length bs - ByteString.length dropped) bs,+ ByteStringUTF8 dropped,+ s')+ where (dropped, s') = dropASCII s0 bs+ dropASCII s bs =+ let suffix = ByteString.drop index bs+ (index, s') = ByteString.foldr f8 id bs (0, s)+ f8 w cont (i, s)+ | w < 0x80, Just s' <- f s (ByteStringUTF8 $ ByteString.singleton w) =+ let i' = succ i :: Int in seq i' $ seq s' $ cont (i', s')+ | otherwise = (i, s)+ in if ByteString.null suffix || unsafeHead suffix < 0x80+ then (suffix, s')+ else dropMultiByte s' suffix+ dropMultiByte s bs =+ case ByteString.findIndex byteStartsCharacter (unsafeTail bs)+ of Nothing -> case f s (ByteStringUTF8 bs)+ of Just s' -> seq s' (ByteString.empty, s')+ Nothing -> (bs, s)+ Just i -> let (hd, tl) = ByteString.splitAt (succ i) bs+ in case f s (ByteStringUTF8 hd)+ of Just s' -> seq s' (dropASCII s' tl)+ Nothing -> (bs, s)+ {-# INLINE spanMaybe' #-} reverse (ByteStringUTF8 bs) = ByteStringUTF8 (ByteString.concat $ List.reverse $ List.map reverseASCII $ groupASCII bs) where reverseASCII b | unsafeHead b < 0x80 = ByteString.reverse b | otherwise = b+ {-# INLINABLE reverse #-} instance TextualMonoid ByteStringUTF8 where singleton = ByteStringUTF8 . fromChar+ {-# INLINE singleton #-} splitCharacterPrefix (ByteStringUTF8 bs) = ByteString.uncons bs >>= uncurry toChar- foldl ft fc a0 (ByteStringUTF8 bs) = List.foldl f a0 (groupASCII bs)- where f a b = let hd = unsafeHead b- in if hd < 0x80- then ByteString.Char8.foldl fc a b- else maybe (ft a $ ByteStringUTF8 b) (fc a . fst) (toChar hd $ unsafeTail b)- foldl' ft fc a0 (ByteStringUTF8 bs) = List.foldl' f a0 (groupASCII bs)- where f a b = let hd = unsafeHead b- in if hd < 0x80- then ByteString.Char8.foldl' fc a b- else maybe (ft a $ ByteStringUTF8 b) (fc a . fst) (toChar hd $ unsafeTail b)- foldr ft fc a0 (ByteStringUTF8 bs) = List.foldr f a0 (groupASCII bs)- where f b a = let hd = unsafeHead b- in if hd < 0x80- then ByteString.Char8.foldr fc a b- else maybe (ft (ByteStringUTF8 b) a) (flip fc a . fst) (toChar hd $ unsafeTail b)+ {-# INLINE splitCharacterPrefix #-}+ foldl ft fc a0 (ByteStringUTF8 bs) = case ByteString.Char8.foldl f (a0, []) bs+ of (a, []) -> a+ (a, acc) -> multiByte a acc+ where f (a, []) c | c < '\x80' = (fc a c, [])+ | otherwise = (a, [fromIntegral $ ord c])+ f (a, acc) c | c < '\x80' = (fc (multiByte a acc) c, [])+ | c < '\xC0' = (a, fromIntegral (ord c) : acc)+ | otherwise = (multiByte a acc, [fromIntegral $ ord c])+ multiByte a acc = reverseBytesToChar (ft a . ByteStringUTF8) (fc a) acc+ {-# INLINE foldl #-}+ foldl' ft fc a0 (ByteStringUTF8 bs) = case ByteString.Char8.foldl' f (a0, []) bs+ of (a, []) -> a+ (a, acc) -> multiByte a acc+ where f (a, []) c | c < '\x80' = (fc a c, [])+ | otherwise = seq a (a, [fromIntegral $ ord c])+ f (a, acc) c | seq a c < '\x80' = let a' = multiByte a acc in seq a' (fc a' c, [])+ | c < '\xC0' = (a, fromIntegral (ord c) : acc)+ | otherwise = let a' = multiByte a acc in seq a' (a', [fromIntegral $ ord c])+ multiByte a acc = reverseBytesToChar (ft a . ByteStringUTF8) (fc a) acc+ + {-# INLINE foldl' #-}+ foldr ft fc a0 (ByteStringUTF8 bs) = case ByteString.Char8.foldr f (a0, []) bs+ of (a, []) -> a+ (a, acc) -> multiByte a acc+ where f c (a, []) | c < '\x80' = (fc c a, [])+ | otherwise = (a, [fromIntegral $ ord c])+ f c (a, acc) | c < '\x80' = (fc c (multiByte a acc), [])+ | c < '\xC0' = (a, fromIntegral (ord c) : acc)+ | otherwise = (multiByte a acc, [fromIntegral $ ord c])+ multiByte a acc = reverseBytesToChar ((`ft` a) . ByteStringUTF8) (`fc` a) acc+ {-# INLINE foldr #-} dropWhile pb pc (ByteStringUTF8 bs) = ByteStringUTF8 $ dropASCII bs where dropASCII rest = case ByteString.Char8.findIndex (\c-> c > '\x7f' || not (pc c)) rest of Nothing -> ByteString.empty@@ -176,16 +271,97 @@ then dropASCII (unsafeDrop j rest) else rest _ -> rest+ {-# INLINE dropWhile #-} takeWhile pb pc utf8@(ByteStringUTF8 bs) =- ByteStringUTF8 $ ByteString.take (ByteString.length bs - ByteString.length suffix) bs- where ByteStringUTF8 suffix = Textual.dropWhile pb pc utf8- span pb pc utf8@(ByteStringUTF8 bs) =- wrapPair $ ByteString.splitAt (ByteString.length bs - ByteString.length suffix) bs+ ByteStringUTF8 $ unsafeTake (ByteString.length bs - ByteString.length suffix) bs where ByteStringUTF8 suffix = Textual.dropWhile pb pc utf8+ {-# INLINE takeWhile #-}+ span pb pc utf8@(ByteStringUTF8 bs) = (ByteStringUTF8 $ unsafeTake (ByteString.length bs - ByteString.length suffix') bs, suffix)+ where suffix@(ByteStringUTF8 suffix') = Textual.dropWhile pb pc utf8+ {-# INLINE span #-} break pb pc = Textual.span (not . pb) (not . pc)+ {-# INLINE break #-}+ spanMaybe s0 ft fc (ByteStringUTF8 bs) =+ let inner i s+ | i < len =+ let w = unsafeIndex bs i+ in if w < 0x80+ then case fc s (w2c w)+ of Just s' -> inner (i + 1) s'+ Nothing -> done i s+ else case splitCharacterPrefix (ByteStringUTF8 $ unsafeDrop i bs)+ of Just (c, ByteStringUTF8 rest) | Just s' <- fc s c -> inner (len - ByteString.length rest) s'+ Nothing -> let j = succ (headIndex $ drop (i + 1) bs)+ in case ft s (ByteStringUTF8 $ ByteString.take j $ unsafeDrop i bs)+ of Just s' -> inner (i + j) s'+ Nothing -> done i s+ _ -> done i s+ | otherwise = done i s+ done i s = i `seq` s `seq` (ByteStringUTF8 $ unsafeTake i bs, ByteStringUTF8 $ unsafeDrop i bs, s)+ len = ByteString.length bs+ in inner 0 s0+ {-# INLINE spanMaybe #-}+ spanMaybe' s0 ft fc (ByteStringUTF8 bs) =+ let inner i s+ | i < len =+ s `seq`+ let w = unsafeIndex bs i+ in if w < 0x80+ then case fc s (w2c w)+ of Just s' -> inner (i + 1) s'+ Nothing -> done i s+ else case splitCharacterPrefix (ByteStringUTF8 $ unsafeDrop i bs)+ of Just (c, ByteStringUTF8 rest) | Just s' <- fc s c -> inner (len - ByteString.length rest) s'+ Nothing -> let j = succ (headIndex $ drop (i + 1) bs)+ in case ft s (ByteStringUTF8 $ ByteString.take j $ unsafeDrop i bs)+ of Just s' -> inner (i + j) s'+ Nothing -> done i s+ _ -> done i s+ | otherwise = done i s+ done i s = i `seq` s `seq` (ByteStringUTF8 $ unsafeTake i bs, ByteStringUTF8 $ unsafeDrop i bs, s)+ len = ByteString.length bs+ in inner 0 s0+ {-# INLINE spanMaybe' #-}+ find p (ByteStringUTF8 bs) = loop bs+ where loop bs = case ByteString.Char8.findIndex (\c-> c >= '\x80' || p c) bs+ of Nothing -> Nothing+ Just i -> let x = unsafeIndex bs i+ bs' = unsafeDrop (i + 1) bs+ in if x < 0x80+ then Just (w2c x)+ else case toChar x bs'+ of Just (c, ByteStringUTF8 rest) | p c -> Just c+ | otherwise -> loop rest+ Nothing -> loop (ByteString.dropWhile (not . byteStartsCharacter) bs')+ {-# INLINE find #-} +reverseBytesToChar :: (ByteString -> a) -> (Char -> a) -> [Word8] -> a+reverseBytesToChar ft fc [w] = if w < 0x80 then fc (w2c w) else ft (ByteString.singleton w)+reverseBytesToChar ft fc [b0, b1] =+ assert (0x80 <= b0 && b0 < 0xC0 && 0xC0 <= b1) $+ if b1 < 0xE0+ then fc (chr (shiftL (fromIntegral b1 .&. 0x1F) 6 .|. fromIntegral b0 .&. 0x3F))+ else ft (ByteString.pack [b1, b0])+reverseBytesToChar ft fc [b0, b1, b2] =+ assert (0x80 <= b0 && b0 < 0xC0 && 0x80 <= b1 && b1 < 0xC0 && 0xC0 <= b2) $+ if (0xE0 < b2 || 0xE0 == b2 && 0xA0 <= b1) && b2 < 0xF0+ then fc (chr (shiftL (fromIntegral b2 .&. 0xF) 12+ .|. shiftL (fromIntegral b1 .&. 0x3F) 6+ .|. fromIntegral b0 .&. 0x3F))+ else ft (ByteString.pack [b2, b1, b0])+reverseBytesToChar ft fc [b0, b1, b2, b3] =+ assert (0x80 <= b0 && b0 < 0xC0 && 0x80 <= b1 && b1 < 0xC0 && 0x80 <= b2 && b2 < 0xC0 && 0xC0 <= b3) $+ if (0xF0 < b3 || 0xF0 == b3 && 0xA0 <= b2) && b3 < 0xF4+ then fc (chr (shiftL (fromIntegral b3 .&. 0x7) 18+ .|. shiftL (fromIntegral b2 .&. 0x3F) 12+ .|. shiftL (fromIntegral b1 .&. 0x3F) 6+ .|. fromIntegral b0 .&. 0x3F))+ else ft (ByteString.pack [b3, b2, b1, b0])+ wrapPair (bs1, bs2) = (ByteStringUTF8 bs1, ByteStringUTF8 bs2)+{-# INLINE wrapPair #-} wrapTriple (bs1, bs2, bs3) = (ByteStringUTF8 bs1, ByteStringUTF8 bs2, ByteStringUTF8 bs3)+{-# INLINE wrapTriple #-} fromChar :: Char -> ByteString fromChar c | c < '\x80' = ByteString.Char8.singleton c@@ -201,7 +377,7 @@ where n = ord c toChar :: Word8 -> ByteString -> Maybe (Char, ByteStringUTF8)-toChar hd tl | hd < 0x80 = Just (chr $ fromIntegral hd, ByteStringUTF8 tl)+toChar hd tl | hd < 0x80 = Just (w2c hd, ByteStringUTF8 tl) | hd < 0xC2 = Nothing | hd < 0xE0 = do (b0, t0) <- ByteString.uncons tl if headIndex tl == 1@@ -232,11 +408,14 @@ groupASCII :: ByteString -> [ByteString] groupASCII = ByteString.groupBy continued where continued a b = (a < 0x80) == (b < 0x80) && b < 0xC0+{-# INLINE groupASCII #-} headIndex bs = fromMaybe (ByteString.length bs) $ ByteString.findIndex byteStartsCharacter bs+{-# INLINE headIndex #-} byteStartsCharacter :: Word8 -> Bool byteStartsCharacter b = b < 0x80 || b >= 0xC0+{-# INLINE byteStartsCharacter #-} charStartIndex :: Int -> ByteString -> Int charStartIndex n _ | n <= 0 = 0@@ -244,3 +423,4 @@ case List.drop (pred n) (ByteString.findIndices byteStartsCharacter $ ByteString.drop 1 bs) of [] -> ByteString.length bs k:_ -> succ k+{-# INLINE charStartIndex #-}
Data/Monoid/Null.hs view
@@ -85,15 +85,19 @@ instance MonoidNull ByteString.ByteString where null = ByteString.null+ {-# INLINE null #-} instance MonoidNull LazyByteString.ByteString where null = LazyByteString.null+ {-# INLINE null #-} instance MonoidNull Text.Text where null = Text.null+ {-# INLINE null #-} instance MonoidNull LazyText.Text where null = LazyText.null+ {-# INLINE null #-} instance Ord k => MonoidNull (Map.Map k v) where null = Map.null
Data/Monoid/Textual.hs view
@@ -28,6 +28,7 @@ import qualified Data.Sequence as Sequence import qualified Data.Vector as Vector import Data.String (IsString(fromString))+import Data.Int (Int64) import Data.Monoid.Null (MonoidNull (null)) import Data.Monoid.Cancellative (LeftReductiveMonoid, LeftGCDMonoid)@@ -112,7 +113,7 @@ -- | Strict version of 'foldl'. foldl' :: (a -> t -> a) -> (a -> Char -> a) -> a -> t -> a -- | The first argument folds over the non-character prime factors, the second over characters. Otherwise equivalent- -- to 'List.foldr' from "Data.List".+ -- to 'List.foldl\'' from "Data.List". foldr :: (t -> a -> a) -> (Char -> a -> a) -> a -> t -> a -- | Equivalent to 'List.scanl' from "Data.List" when applied to a 'String', but preserves all non-character data.@@ -144,6 +145,10 @@ break :: (t -> Bool) -> (Char -> Bool) -> t -> (t, t) -- | 'span pt pc t' is equivalent to |(takeWhile pt pc t, dropWhile pt pc t)|. span :: (t -> Bool) -> (Char -> Bool) -> t -> (t, t)+ -- | A stateful variant of 'span', threading the result of the test function as long as it returns 'Just'.+ spanMaybe :: s -> (s -> t -> Maybe s) -> (s -> Char -> Maybe s) -> t -> (t, t, s)+ -- | Strict version of 'spanMaybe'.+ spanMaybe' :: s -> (s -> t -> Maybe s) -> (s -> Char -> Maybe s) -> t -> (t, t, s) -- | Splits the monoid into components delimited by character separators satisfying the given predicate. The -- characters satisfying the predicate are not a part of the result. --@@ -189,12 +194,42 @@ dropWhile pt pc = snd . span pt pc span pt pc = Factorial.span (\prime-> maybe (pt prime) pc (characterPrefix prime)) break pt pc = Factorial.break (\prime-> maybe (pt prime) pc (characterPrefix prime))+ spanMaybe s0 ft fc t0 = spanAfter id s0 t0+ where spanAfter g s t = case Factorial.splitPrimePrefix t+ of Just (prime, rest) | Just s' <- maybe (ft s prime) (fc s) (characterPrefix prime) ->+ spanAfter (g . mappend prime) s' rest+ | otherwise -> (g mempty, t, s)+ Nothing -> (t0, t, s)+ spanMaybe' s0 ft fc t0 = spanAfter id s0 t0+ where spanAfter g s t = seq s $+ case Factorial.splitPrimePrefix t+ of Just (prime, rest) | Just s' <- maybe (ft s prime) (fc s) (characterPrefix prime) ->+ spanAfter (g . mappend prime) s' rest+ | otherwise -> (g mempty, t, s)+ Nothing -> (t0, t, s) split p m = prefix : splitRest where (prefix, rest) = break (const False) p m splitRest = case splitCharacterPrefix rest of Nothing -> [] Just (_, tail) -> split p tail find p = foldr (const id) (\c r-> if p c then Just c else r) Nothing+ {-# INLINE characterPrefix #-}+ {-# INLINE concatMap #-}+ {-# INLINE dropWhile #-}+ {-# INLINE find #-}+ {-# INLINE fromText #-}+ {-# INLINE map #-}+ {-# INLINE mapAccumL #-}+ {-# INLINE mapAccumR #-}+ {-# INLINE scanl #-}+ {-# INLINE scanl1 #-}+ {-# INLINE scanr #-}+ {-# INLINE scanr1 #-}+ {-# INLINE singleton #-}+ {-# INLINE spanMaybe #-}+ {-# INLINE spanMaybe' #-}+ {-# INLINE split #-}+ {-# INLINE takeWhile #-} foldlChars f (t, c1) c2 = (mappend t (singleton c'), c') where c' = f c1 c2@@ -230,7 +265,40 @@ dropWhile _ = List.dropWhile break _ = List.break span _ = List.span+ spanMaybe s0 ft fc l = (prefix' [], suffix' [], s')+ where (prefix', suffix', s', live') = List.foldl' g (id, id, s0, True) l+ g (prefix, suffix, s, live) c | live, Just s' <- fc s c = (prefix . (c:), id, s', True)+ | otherwise = (prefix, suffix . (c:), s, False)+ spanMaybe' s0 ft fc l = (prefix' [], suffix' [], s')+ where (prefix', suffix', s', live') = List.foldl' g (id, id, s0, True) l+ g (prefix, suffix, s, live) c | live, Just s' <- fc s c = seq s' (prefix . (c:), id, s', True)+ | otherwise = (prefix, suffix . (c:), s, False) find = List.find+ {-# INLINE all #-}+ {-# INLINE any #-}+ {-# INLINE break #-}+ {-# INLINE characterPrefix #-}+ {-# INLINE concatMap #-}+ {-# INLINE dropWhile #-}+ {-# INLINE find #-}+ {-# INLINE foldl #-}+ {-# INLINE foldl' #-}+ {-# INLINE foldr #-}+ {-# INLINE fromText #-}+ {-# INLINE map #-}+ {-# INLINE mapAccumL #-}+ {-# INLINE mapAccumR #-}+ {-# INLINE scanl #-}+ {-# INLINE scanl1 #-}+ {-# INLINE scanr #-}+ {-# INLINE scanr1 #-}+ {-# INLINE singleton #-}+ {-# INLINE span #-}+ {-# INLINE spanMaybe #-}+ {-# INLINE spanMaybe' #-}+ {-# INLINE split #-}+ {-# INLINE splitCharacterPrefix #-}+ {-# INLINE takeWhile #-} instance TextualMonoid Text where fromText = id@@ -257,8 +325,41 @@ dropWhile _ = Text.dropWhile break _ = Text.break span _ = Text.span+ spanMaybe s0 ft fc t = case Text.foldr g id t (0, s0)+ of (i, s') | (prefix, suffix) <- Text.splitAt i t -> (prefix, suffix, s')+ where g c cont (i, s) | Just s' <- fc s c = let i' = succ i :: Int in seq i' $ cont (i', s')+ | otherwise = (i, s)+ spanMaybe' s0 ft fc t = case Text.foldr g id t (0, s0)+ of (i, s') | (prefix, suffix) <- Text.splitAt i t -> (prefix, suffix, s')+ where g c cont (i, s) | Just s' <- fc s c = let i' = succ i :: Int in seq i' $ seq s' $ cont (i', s')+ | otherwise = (i, s) split = Text.split find = Text.find+ {-# INLINE all #-}+ {-# INLINE any #-}+ {-# INLINE break #-}+ {-# INLINE characterPrefix #-}+ {-# INLINE concatMap #-}+ {-# INLINE dropWhile #-}+ {-# INLINE find #-}+ {-# INLINE foldl #-}+ {-# INLINE foldl' #-}+ {-# INLINE foldr #-}+ {-# INLINE fromText #-}+ {-# INLINE map #-}+ {-# INLINE mapAccumL #-}+ {-# INLINE mapAccumR #-}+ {-# INLINE scanl #-}+ {-# INLINE scanl1 #-}+ {-# INLINE scanr #-}+ {-# INLINE scanr1 #-}+ {-# INLINE singleton #-}+ {-# INLINE span #-}+ {-# INLINE spanMaybe #-}+ {-# INLINE spanMaybe' #-}+ {-# INLINE split #-}+ {-# INLINE splitCharacterPrefix #-}+ {-# INLINE takeWhile #-} instance TextualMonoid LazyText.Text where fromText = LazyText.fromStrict@@ -285,8 +386,41 @@ dropWhile _ = LazyText.dropWhile break _ = LazyText.break span _ = LazyText.span+ spanMaybe s0 ft fc t = case LazyText.foldr g id t (0, s0)+ of (i, s') | (prefix, suffix) <- LazyText.splitAt i t -> (prefix, suffix, s')+ where g c cont (i, s) | Just s' <- fc s c = let i' = succ i :: Int64 in seq i' $ cont (i', s')+ | otherwise = (i, s)+ spanMaybe' s0 ft fc t = case LazyText.foldr g id t (0, s0)+ of (i, s') | (prefix, suffix) <- LazyText.splitAt i t -> (prefix, suffix, s')+ where g c cont (i, s) | Just s' <- fc s c = let i' = succ i :: Int64 in seq i' $ seq s' $ cont (i', s')+ | otherwise = (i, s) split = LazyText.split find = LazyText.find+ {-# INLINE all #-}+ {-# INLINE any #-}+ {-# INLINE break #-}+ {-# INLINE characterPrefix #-}+ {-# INLINE concatMap #-}+ {-# INLINE dropWhile #-}+ {-# INLINE find #-}+ {-# INLINE foldl #-}+ {-# INLINE foldl' #-}+ {-# INLINE foldr #-}+ {-# INLINE fromText #-}+ {-# INLINE map #-}+ {-# INLINE mapAccumL #-}+ {-# INLINE mapAccumR #-}+ {-# INLINE scanl #-}+ {-# INLINE scanl1 #-}+ {-# INLINE scanr #-}+ {-# INLINE scanr1 #-}+ {-# INLINE singleton #-}+ {-# INLINE span #-}+ {-# INLINE spanMaybe #-}+ {-# INLINE spanMaybe' #-}+ {-# INLINE split #-}+ {-# INLINE splitCharacterPrefix #-}+ {-# INLINE takeWhile #-} instance IsString (Sequence.Seq Char) where fromString = Sequence.fromList@@ -319,7 +453,40 @@ dropWhile _ = Sequence.dropWhileL break _ = Sequence.breakl span _ = Sequence.spanl+ spanMaybe s0 ft fc b = case Foldable.foldr g id b (0, s0)+ of (i, s') | (prefix, suffix) <- Sequence.splitAt i b -> (prefix, suffix, s')+ where g c cont (i, s) | Just s' <- fc s c = let i' = succ i :: Int in seq i' $ cont (i', s')+ | otherwise = (i, s)+ spanMaybe' s0 ft fc b = case Foldable.foldr g id b (0, s0)+ of (i, s') | (prefix, suffix) <- Sequence.splitAt i b -> (prefix, suffix, s')+ where g c cont (i, s) | Just s' <- fc s c = let i' = succ i :: Int in seq i' $ seq s' $ cont (i', s')+ | otherwise = (i, s) find = Foldable.find+ {-# INLINE all #-}+ {-# INLINE any #-}+ {-# INLINE break #-}+ {-# INLINE characterPrefix #-}+ {-# INLINE concatMap #-}+ {-# INLINE dropWhile #-}+ {-# INLINE find #-}+ {-# INLINE foldl #-}+ {-# INLINE foldl' #-}+ {-# INLINE foldr #-}+ {-# INLINE fromText #-}+ {-# INLINE map #-}+ {-# INLINE mapAccumL #-}+ {-# INLINE mapAccumR #-}+ {-# INLINE scanl #-}+ {-# INLINE scanl1 #-}+ {-# INLINE scanr #-}+ {-# INLINE scanr1 #-}+ {-# INLINE singleton #-}+ {-# INLINE span #-}+ {-# INLINE spanMaybe #-}+ {-# INLINE spanMaybe' #-}+ {-# INLINE split #-}+ {-# INLINE splitCharacterPrefix #-}+ {-# INLINE takeWhile #-} instance IsString (Vector.Vector Char) where fromString = Vector.fromList@@ -356,4 +523,39 @@ dropWhile _ = Vector.dropWhile break _ = Vector.break span _ = Vector.span+ spanMaybe s0 ft fc v = case Vector.ifoldr g Left v s0+ of Left s' -> (v, Vector.empty, s')+ Right (i, s') | (prefix, suffix) <- Vector.splitAt i v -> (prefix, suffix, s')+ where g i c cont s | Just s' <- fc s c = cont s'+ | otherwise = Right (i, s)+ spanMaybe' s0 ft fc v = case Vector.ifoldr' g Left v s0+ of Left s' -> (v, Vector.empty, s')+ Right (i, s') | (prefix, suffix) <- Vector.splitAt i v -> (prefix, suffix, s')+ where g i c cont s | Just s' <- fc s c = seq s' (cont s')+ | otherwise = Right (i, s) find = Vector.find+ {-# INLINE all #-}+ {-# INLINE any #-}+ {-# INLINE break #-}+ {-# INLINE characterPrefix #-}+ {-# INLINE concatMap #-}+ {-# INLINE dropWhile #-}+ {-# INLINE find #-}+ {-# INLINE foldl #-}+ {-# INLINE foldl' #-}+ {-# INLINE foldr #-}+ {-# INLINE fromText #-}+ {-# INLINE map #-}+ {-# INLINE mapAccumL #-}+ {-# INLINE mapAccumR #-}+ {-# INLINE scanl #-}+ {-# INLINE scanl1 #-}+ {-# INLINE scanr #-}+ {-# INLINE scanr1 #-}+ {-# INLINE singleton #-}+ {-# INLINE span #-}+ {-# INLINE spanMaybe #-}+ {-# INLINE spanMaybe' #-}+ {-# INLINE split #-}+ {-# INLINE splitCharacterPrefix #-}+ {-# INLINE takeWhile #-}
Test/TestMonoidSubclasses.hs view
@@ -12,7 +12,7 @@ import Prelude hiding (foldl, foldr, gcd, length, null, reverse, span, splitAt, takeWhile) import Test.QuickCheck (Arbitrary, CoArbitrary, Property, Gen,- quickCheck, arbitrary, coarbitrary, property, label, forAll, variant, whenFail, (.&&.))+ quickCheck, arbitrary, coarbitrary, property, label, forAll, mapSize, variant, whenFail, (.&&.)) import Test.QuickCheck.Instances () import Control.Applicative (Applicative(..), liftA2)@@ -58,8 +58,8 @@ First(First), Last(Last), Sum(Sum), Product(Product)) import Data.Monoid.Null (MonoidNull, PositiveMonoid, null) import Data.Monoid.Factorial (FactorialMonoid, StableFactorialMonoid, - factors, splitPrimePrefix, splitPrimeSuffix, primePrefix, primeSuffix,- foldl, foldl', foldr, length, reverse, span, split, splitAt)+ factors, splitPrimePrefix, splitPrimeSuffix, primePrefix, primeSuffix, inits, tails,+ foldl, foldl', foldr, length, reverse, span, spanMaybe, split, splitAt) import Data.Monoid.Cancellative (CommutativeMonoid, ReductiveMonoid, LeftReductiveMonoid, RightReductiveMonoid, CancellativeMonoid, LeftCancellativeMonoid, RightCancellativeMonoid, GCDMonoid, LeftGCDMonoid, RightGCDMonoid,@@ -344,11 +344,14 @@ ("splitPrimeSuffix", FactorialTest checkSplitPrimeSuffix), ("primePrefix", FactorialTest checkPrimePrefix), ("primeSuffix", FactorialTest checkPrimeSuffix),+ ("inits", FactorialTest checkInits),+ ("tails", FactorialTest checkTails), ("foldl", FactorialTest checkLeftFold), ("foldl'", FactorialTest checkLeftFold'), ("foldr", FactorialTest checkRightFold), ("length", FactorialTest checkLength), ("span", FactorialTest checkSpan),+ ("spanMaybe", FactorialTest checkSpanMaybe), ("split", FactorialTest checkSplit), ("splitAt", FactorialTest checkSplitAt), ("reverse", FactorialTest checkReverse),@@ -420,6 +423,12 @@ checkPrimeSuffix (FactorialMonoidInstance (_ :: a)) = forAll (arbitrary :: Gen a) (\a-> primeSuffix a == maybe mempty snd (splitPrimeSuffix a)) +checkInits (FactorialMonoidInstance (_ :: a)) =+ mapSize (`div` 5) $ forAll (arbitrary :: Gen a) (\a-> inits a == List.map mconcat (List.inits $ factors a))++checkTails (FactorialMonoidInstance (_ :: a)) =+ mapSize (`div` 5) $ forAll (arbitrary :: Gen a) (\a-> tails a == List.map mconcat (List.tails $ factors a))+ checkLeftFold (FactorialMonoidInstance (_ :: a)) = forAll (arbitrary :: Gen a) (\a-> foldl (flip (:)) [] a == List.foldl (flip (:)) [] (factors a)) @@ -436,6 +445,14 @@ where check p a = span p a == (mconcat l, mconcat r) where (l, r) = List.span p (factors a) +checkSpanMaybe (FactorialMonoidInstance (_ :: a)) = property $ \(f, s)-> forAll (arbitrary :: Gen a) (check f (s :: Bool))+ where check f s0 a = a == prefix <> suffix+ && foldMaybe prefix == Just s'+ && (null suffix || f s' (primePrefix suffix) == Nothing)+ where (prefix, suffix, s') = spanMaybe s0 f a+ foldMaybe = foldl g (Just s0)+ g s m = s >>= flip f m+ checkSplit (FactorialMonoidInstance (_ :: a)) = forAll (arbitrary :: Gen a) check where check a = property (\pred-> all (all (not . pred) . factors) (split pred a)) .&&. property (\prime-> mconcat (intersperse prime $ split (== prime) a) == a)@@ -750,6 +767,9 @@ instance Show a => Show (a -> Bool) where show _ = "predicate"++instance Show a => Show (Bool -> a -> Maybe Bool) where+ show _ = "stateful predicate" instance (PositiveMonoid a, MonoidNull b) => PositiveMonoid (a, b)
monoid-subclasses.cabal view
@@ -1,5 +1,5 @@ Name: monoid-subclasses-Version: 0.3.6.1+Version: 0.3.6.2 Cabal-Version: >= 1.10 Build-Type: Simple Synopsis: Subclasses of Monoid@@ -11,7 +11,7 @@ License: BSD3 License-file: BSD3-LICENSE.txt-Copyright: (c) 2013 Mario Blazevic+Copyright: (c) 2013-2014 Mario Blazevic Author: Mario Blazevic Maintainer: Mario Blazevic <blamario@yahoo.com> Homepage: https://github.com/blamario/monoid-subclasses/