packages feed

utility-ht 0.0.11 → 0.0.12

raw patch · 17 files changed

+477/−47 lines, 17 files

Files

+ src/Control/Applicative/HT.hs view
@@ -0,0 +1,31 @@+module Control.Applicative.HT where++import qualified Data.Tuple.HT as Tuple++import Control.Applicative (Applicative, liftA2, liftA3, (<$>), (<*>), )++mapPair :: (Applicative f) => (a -> f c, b -> f d) -> (a,b) -> f (c,d)+mapPair fg = uncurry (liftA2 (,)) . Tuple.mapPair fg++mapTriple ::+   (Applicative m) => (a -> m d, b -> m e, c -> m f) -> (a,b,c) -> m (d,e,f)+mapTriple fgh = Tuple.uncurry3 (liftA3 (,,)) . Tuple.mapTriple fgh+++{-# INLINE liftA4 #-}+liftA4 :: Applicative f =>+   (a -> b -> c -> d -> e) ->+   f a -> f b -> f c -> f d -> f e+liftA4 f a b c d = f <$> a <*> b <*> c <*> d++{-# INLINE liftA5 #-}+liftA5 :: Applicative f =>+   (a -> b -> c -> d -> e -> g) ->+   f a -> f b -> f c -> f d -> f e -> f g+liftA5 f a b c d e = f <$> a <*> b <*> c <*> d <*> e++{-# INLINE liftA6 #-}+liftA6 :: Applicative f =>+   (a -> b -> c -> d -> e -> g -> h) ->+   f a -> f b -> f c -> f d -> f e -> f g -> f h+liftA6 f a b c d e g = f <$> a <*> b <*> c <*> d <*> e <*> g
src/Control/Functor/HT.hs view
@@ -28,6 +28,24 @@ unzip3 :: Functor f => f (a, b, c) -> (f a, f b, f c) unzip3 x = (fmap fst3 x, fmap snd3 x, fmap thd3 x) ++mapFst :: Functor f => (a -> f c) -> (a, b) -> f (c, b)+mapFst f ~(a,b) = fmap (flip (,) b) $ f a++mapSnd :: Functor f => (b -> f c) -> (a, b) -> f (a, c)+mapSnd f ~(a,b) = fmap ((,) a) $ f b+++mapFst3 :: Functor f => (a -> f d) -> (a,b,c) -> f (d,b,c)+mapFst3 f ~(a,b,c) = fmap (\x -> (x,b,c)) $ f a++mapSnd3 :: Functor f => (b -> f d) -> (a,b,c) -> f (a,d,c)+mapSnd3 f ~(a,b,c) = fmap (\x -> (a,x,c)) $ f b++mapThd3 :: Functor f => (c -> f d) -> (a,b,c) -> f (a,b,d)+mapThd3 f ~(a,b,c) = fmap ((,,) a b) $ f c++ {- | Generalization of 'Data.List.HT.outerProduct'. -}
src/Control/Monad/HT.hs view
@@ -45,6 +45,15 @@    in  aux m  {- |+I think this makes only sense in a lazy monad+like @Trans.State.Lazy@ or @IO.Lazy@.+-}+iterate :: Monad m => (a -> m a) -> a -> m [a]+iterate f =+   let go x = lift (x:) $ go =<< f x+   in  go++{- | Lazy monadic conjunction. That is, when the first action returns @False@, then @False@ is immediately returned, without running the second action.@@ -84,6 +93,7 @@ chain :: (Monad m) => [a -> m a] -> (a -> m a) chain = foldr (flip (<=<)) return +-- there is also mfilter, but this should be part of Control.Monad.Plus filter :: Monad m => (a -> m Bool) -> [a] -> m [a] filter = M.filterM 
+ src/Data/Bits/HT.hs view
@@ -0,0 +1,20 @@+module Data.Bits.HT where++import Data.Bits (Bits, shiftL, shiftR)+++infixl 7 .<<., .>>.++{- |+Infix variant of 'shiftL'.+Precedence is chosen like multiplication since @a .<<. k == a * 2^k@.+-}+(.<<.) :: Bits a => a -> Int -> a+(.<<.) = shiftL++{- |+Infix variant of 'shiftR'.+Precedence is chosen like division since @a .>>. k == a / 2^k@.+-}+(.>>.) :: Bits a => a -> Int -> a+(.>>.) = shiftR
src/Data/List/HT.hs view
@@ -11,6 +11,7 @@    -- * Split    L.chop,    L.breakAfter,+   L.takeUntil,    L.segmentAfter,    L.segmentBefore,    L.segmentAfterMaybe,@@ -26,10 +27,12 @@    -- * List processing starting at the end    L.dropRev,    L.takeRev,-   L.dropWhileRev,-   L.takeWhileRev,+   L.splitAtRev,+   dropWhileRev,+   takeWhileRev,    -- * List processing with Maybe and Either    L.maybePrefixOf,+   L.maybeSuffixOf,    L.partitionMaybe,    L.takeWhileJust,    L.unzipEithers,@@ -63,3 +66,12 @@    ) where  import qualified Data.List.HT.Private as L+import qualified Data.List.Reverse.StrictElement as Rev++{-# DEPRECATED dropWhileRev "Use dropWhile from Data.List.Reverse.StrictElement or Data.List.Reverse.StrictSpine instead" #-}+dropWhileRev :: (a -> Bool) -> [a] -> [a]+dropWhileRev = Rev.dropWhile++{-# DEPRECATED takeWhileRev "Use takeWhile from Data.List.Reverse.StrictElement or Data.List.Reverse.StrictSpine instead" #-}+takeWhileRev :: (a -> Bool) -> [a] -> [a]+takeWhileRev = Rev.takeWhile
src/Data/List/HT/Private.hs view
@@ -5,10 +5,12 @@ import Data.Maybe as Maybe (fromMaybe, catMaybes, ) import Data.Maybe.HT       (toMaybe, ) import Control.Monad       (guard, msum, )+import Control.Applicative ((<*>), ) import Data.Tuple.HT       (mapPair, mapFst, mapSnd, forcePair, swap, )  import qualified Data.List.Key.Private   as Key import qualified Data.List.Match.Private as Match+import qualified Data.List.Reverse.StrictElement as Rev  import Prelude hiding (unzip, break, span, ) @@ -180,7 +182,7 @@    in  recourse  -chopAtRun :: (Eq a) => (a -> Bool) -> [a] -> [[a]]+chopAtRun :: (a -> Bool) -> [a] -> [[a]] chopAtRun p =    let recourse [] = [[]]        recourse y =@@ -193,7 +195,10 @@ Like 'break', but splits after the matching element. -} breakAfter :: (a -> Bool) -> [a] -> ([a], [a])-breakAfter p =+breakAfter = breakAfterRec++breakAfterRec :: (a -> Bool) -> [a] -> ([a], [a])+breakAfterRec p =    let recourse [] = ([],[])        recourse (x:xs) =           mapFst (x:) $@@ -202,8 +207,40 @@             else recourse xs    in  forcePair . recourse +{-+The use of 'foldr' might allow for fusion,+but unfortunately this simple implementation would copy the tail of the list.+-}+breakAfterFoldr :: (a -> Bool) -> [a] -> ([a], [a])+breakAfterFoldr p =+   forcePair .+   foldr+      (\x yzs -> mapFst (x:) $ if p x then ([], uncurry (++) yzs) else yzs)+      ([],[]) +breakAfterBreak :: (a -> Bool) -> [a] -> ([a], [a])+breakAfterBreak p xs =+   case break p xs of+      (ys, []) -> (ys, [])+      (ys, z:zs) -> (ys++[z], zs)++breakAfterTakeUntil :: (a -> Bool) -> [a] -> ([a], [a])+breakAfterTakeUntil p xs =+   forcePair $+   (\ys -> (map fst ys, maybe [] (snd . snd) $ viewR ys)) $+   takeUntil (p . fst) $ zip xs $ tail $ tails xs+ {- |+Take all elements until one matches.+The matching element is returned, too.+This is the key difference to @takeWhile (not . p)@.+It holds @takeUntil p xs == fst (breakAfter p xs)@.+-}+takeUntil :: (a -> Bool) -> [a] -> [a]+takeUntil p = foldr (\x ys -> x : if p x then [] else ys) []+++{- | Split the list after each occurence of a terminator. Keep the terminator. There is always a list for the part after the last terminator.@@ -452,43 +489,39 @@ dropRev :: Int -> [a] -> [a] dropRev n xs = Match.take (drop n xs) xs - {- |-Remove the longest suffix of elements satisfying p.-In contrast to @reverse . dropWhile p . reverse@-this works for infinite lists, too.+@splitAtRev n xs == (dropRev n xs, takeRev n xs)@.+It holds @xs == uncurry (++) (splitAtRev n xs)@ -}+splitAtRev :: Int -> [a] -> ([a], [a])+splitAtRev n xs = Match.splitAt (drop n xs) xs++ dropWhileRev :: (a -> Bool) -> [a] -> [a] dropWhileRev p =-   foldr (\x xs -> if p x && null xs then [] else x:xs) []--dropWhileRev' :: (a -> Bool) -> [a] -> [a]-dropWhileRev' p =    concat . init . segmentAfter (not . p) -{- |-Alternative version of @reverse . takeWhile p . reverse@.--}-takeWhileRev :: (a -> Bool) -> [a] -> [a]-takeWhileRev p =+takeWhileRev0 :: (a -> Bool) -> [a] -> [a]+takeWhileRev0 p =    last . segmentAfter (not . p)  {- | Doesn't seem to be superior to the naive implementation. -}-takeWhileRev' :: (a -> Bool) -> [a] -> [a]-takeWhileRev' p =-   (\xs -> if fst (head xs)-             then map snd xs-             else []) .-   last . Key.aux groupBy (==) p+takeWhileRev1 :: (a -> Bool) -> [a] -> [a]+takeWhileRev1 p =+   (\mx ->+      case mx of+         Just (_, xs@((True,_):_)) -> map snd xs+         _ -> []) .+   viewR . Key.aux groupBy (==) p  {- | However it is more inefficient, because of repeatedly appending single elements. :-( -}-takeWhileRev'' :: (a -> Bool) -> [a] -> [a]-takeWhileRev'' p =+takeWhileRev2 :: (a -> Bool) -> [a] -> [a]+takeWhileRev2 p =    foldl (\xs x -> if p x then xs++[x] else []) []  @@ -498,12 +531,18 @@ @maybePrefixOf xs ys@ is @Just zs@ if @xs@ is a prefix of @ys@, where @zs@ is @ys@ without the prefix @xs@. Otherwise it is @Nothing@.+It is the same as 'Data.List.stripPrefix'. -} maybePrefixOf :: Eq a => [a] -> [a] -> Maybe [a] maybePrefixOf (x:xs) (y:ys) = guard (x==y) >> maybePrefixOf xs ys maybePrefixOf [] ys = Just ys maybePrefixOf _  [] = Nothing +maybeSuffixOf :: Eq a => [a] -> [a] -> Maybe [a]+maybeSuffixOf xs ys =+   fmap reverse $ maybePrefixOf (reverse xs) (reverse ys)++ {- | Partition a list into elements which evaluate to @Just@ or @Nothing@ by @f@. @@ -699,7 +738,7 @@ transposeFill =    unfoldr (\xs ->       toMaybe (not (null xs))-         (mapSnd (dropWhileRev null) $ unzipCons xs))+         (mapSnd (Rev.dropWhile null) $ unzipCons xs))  unzipCons :: [[a]] -> ([Maybe a], [[a]]) unzipCons =@@ -732,7 +771,7 @@        zipConc (a:as) (b:bs) = (a++b) : zipConc as bs        zipConc [] bs = bs        zipConc as [] = as-   in  y : zipConc ys (shear' (dropWhileRev null zs))+   in  y : zipConc ys (shear' (Rev.dropWhile null zs))               {- Dropping trailing empty lists is necessary,                  otherwise finite lists are filled with empty lists. -} shear' [] = []@@ -945,6 +984,13 @@ -} mapAdjacent :: (a -> a -> b) -> [a] -> [b] mapAdjacent f xs = zipWith f xs (tail xs)++{- |+<http://mail.haskell.org/libraries/2016-April/026912.html>+-}+mapAdjacentPointfree :: (a -> a -> b) -> [a] -> [b]+mapAdjacentPointfree f = zipWith f <*> tail+  {- | > mapAdjacent f a0 [(a1,b1), (a2,b2), (a3,b3)]
+ src/Data/List/Reverse/StrictElement.hs view
@@ -0,0 +1,44 @@+{- |+The functions in this module process the list formally from the end.+Actually they traverse the list from the start and check every element.+This way they are strict in the elements and lazy in the list spline.+Thus you can apply them to infinite lists.+Use these functions if the list is long or the test is cheap.+-}+module Data.List.Reverse.StrictElement where++import Data.Tuple.HT (mapFst, mapSnd, forcePair, )++import Prelude hiding (dropWhile, takeWhile, span, )+++{- |+Remove the longest suffix of elements satisfying p.+In contrast to @reverse . dropWhile p . reverse@+this works for infinite lists, too.+-}+dropWhile :: (a -> Bool) -> [a] -> [a]+dropWhile p =+   foldr (\x xs -> if p x && null xs then [] else x:xs) []++{- |+Alternative version of @reverse . takeWhile p . reverse@.+-}+takeWhile :: (a -> Bool) -> [a] -> [a]+takeWhile p =+   snd .+   foldr+      (\x xys ->+         (if p x && fst xys then mapSnd (x:) else mapFst (const False)) xys)+      (True, [])++{- |+@span p xs == (dropWhile p xs, takeWhile p xs)@+-}+span :: (a -> Bool) -> [a] -> ([a], [a])+span p =+   forcePair .+   foldr+      (\x xys ->+         (if p x && null (fst xys) then mapSnd else mapFst) (x:) xys)+      ([], [])
+ src/Data/List/Reverse/StrictSpine.hs view
@@ -0,0 +1,41 @@+{- |+The functions in this module process the list from the end.+They do not access elements at the beginning if not necessary.+You can apply the function only to infinite lists.+Use these functions if the list is short and the test is expensive.+-}+module Data.List.Reverse.StrictSpine where++import Data.Tuple.HT (mapFst, mapSnd, forcePair, )++import Prelude hiding (dropWhile, takeWhile, span, )+++{- |+Like @reverse . List.dropWhile p . reverse@.+-}+dropWhile :: (a -> Bool) -> [a] -> [a]+dropWhile p =+   foldr (\x xs -> if null xs && p x then [] else x:xs) []++{- |+Like @reverse . List.takeWhile p . reverse@.+-}+takeWhile :: (a -> Bool) -> [a] -> [a]+takeWhile p =+   snd .+   foldr+      (\x xys ->+         (if fst xys && p x then mapSnd (x:) else mapFst (const False)) xys)+      (True, [])++{- |+@span p xs == (dropWhile p xs, takeWhile p xs)@+-}+span :: (a -> Bool) -> [a] -> ([a], [a])+span p =+   forcePair .+   foldr+      (\x xys ->+         (if null (fst xys) && p x then mapSnd else mapFst) (x:) xys)+      ([], [])
src/Data/String/HT.hs view
@@ -1,8 +1,14 @@ module Data.String.HT where +import qualified Data.List.Reverse.StrictSpine as Rev import Data.Char (isSpace, )-import Data.List.HT (dropWhileRev, ) --- | remove leading and trailing spaces+{- |+Remove leading and trailing spaces.++We use spine strict 'Rev.dropWhile' instead of the element strict version.+This is more efficient for finite 'String's because 'isSpace' is expensive.+The downside is that 'trim' does not work for infinite 'String's.+-} trim :: String -> String-trim = dropWhileRev isSpace . dropWhile isSpace+trim = Rev.dropWhile isSpace . dropWhile isSpace
src/Data/Tuple/HT.hs view
@@ -4,6 +4,7 @@    mapFst,    mapSnd,    swap,+   sortPair,    forcePair,     -- * Triple@@ -36,3 +37,7 @@ {-# INLINE curry3 #-} curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d curry3 f a b c = f (a,b,c)++sortPair, _sortPairMinMax :: (Ord a) => (a,a) -> (a,a)+sortPair (x,y) = if x<=y then (x,y) else (y,x)+_sortPairMinMax (x,y) = (min x y, max x y)
src/Data/Tuple/Lazy.hs view
@@ -15,12 +15,12 @@ where one variant is definitely better than the other one. -} {--Instead of lazy pattern matching with \code{(x,y)}+Instead of lazy pattern matching with \code{(a,b)} we may use \function{fst} and \function{snd}. -} {-# INLINE mapPair #-} mapPair :: (a -> c, b -> d) -> (a,b) -> (c,d)-mapPair ~(f,g) ~(x,y) = (f x, g y)+mapPair ~(f,g) ~(a,b) = (f a, g b)  -- | 'Control.Arrow.first' {-# INLINE mapFst #-}@@ -32,21 +32,25 @@ mapSnd :: (b -> c) -> (a,b) -> (a,c) mapSnd f ~(a,b) = (a, f b) +{-# INLINE zipWithPair #-}+zipWithPair :: (a -> c -> e, b -> d -> f) -> (a,b) -> (c,d) -> (e,f)+zipWithPair ~(e,f) ~(a,b) ~(c,d) = (e a c, f b d) + {-# INLINE swap #-} swap :: (a,b) -> (b,a)-swap ~(x,y) = (y,x)+swap ~(a,b) = (b,a)  {-# INLINE forcePair #-} forcePair :: (a,b) -> (a,b)-forcePair ~(x,y) = (x,y)+forcePair ~(a,b) = (a,b)   -- * Triple  {-# INLINE mapTriple #-} mapTriple :: (a -> d, b -> e, c -> f) -> (a,b,c) -> (d,e,f)-mapTriple ~(f,g,h) ~(x,y,z) = (f x, g y, h z)+mapTriple ~(f,g,h) ~(a,b,c) = (f a, g b, h c)  {-# INLINE mapFst3 #-} mapFst3 :: (a -> d) -> (a,b,c) -> (d,b,c)@@ -59,6 +63,11 @@ {-# INLINE mapThd3 #-} mapThd3 :: (c -> d) -> (a,b,c) -> (a,b,d) mapThd3 f ~(a,b,c) = (a, b, f c)++{-# INLINE zipWithTriple #-}+zipWithTriple ::+   (a -> d -> g, b -> e -> h, c -> f -> i) -> (a,b,c) -> (d,e,f) -> (g,h,i)+zipWithTriple ~(g,h,i) ~(a,b,c) ~(d,e,f) = (g a d, h b e, i c f)  {-# INLINE uncurry3 #-} uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)
src/Data/Tuple/Strict.hs view
@@ -4,7 +4,7 @@  {-# INLINE mapPair #-} mapPair :: (a -> c, b -> d) -> (a,b) -> (c,d)-mapPair (f,g) (x,y) = (f x, g y)+mapPair (f,g) (a,b) = (f a, g b)  {-# INLINE mapFst #-} mapFst :: (a -> c) -> (a,b) -> (c,b)@@ -14,17 +14,21 @@ mapSnd :: (b -> c) -> (a,b) -> (a,c) mapSnd f (a,b) = (a, f b) +{-# INLINE zipWithPair #-}+zipWithPair :: (a -> c -> e, b -> d -> f) -> (a,b) -> (c,d) -> (e,f)+zipWithPair (e,f) (a,b) (c,d) = (e a c, f b d) + {-# INLINE swap #-} swap :: (a,b) -> (b,a)-swap (x,y) = (y,x)+swap (a,b) = (b,a)   -- * Triple  {-# INLINE mapTriple #-} mapTriple :: (a -> d, b -> e, c -> f) -> (a,b,c) -> (d,e,f)-mapTriple (f,g,h) (x,y,z) = (f x, g y, h z)+mapTriple (f,g,h) (a,b,c) = (f a, g b, h c)  {-# INLINE mapFst3 #-} mapFst3 :: (a -> d) -> (a,b,c) -> (d,b,c)@@ -37,6 +41,11 @@ {-# INLINE mapThd3 #-} mapThd3 :: (c -> d) -> (a,b,c) -> (a,b,d) mapThd3 f (a,b,c) = (a, b, f c)++{-# INLINE zipWithTriple #-}+zipWithTriple ::+   (a -> d -> g, b -> e -> h, c -> f -> i) -> (a,b,c) -> (d,e,f) -> (g,h,i)+zipWithTriple (g,h,i) (a,b,c) (d,e,f) = (g a d, h b e, i c f)  {-# INLINE uncurry3 #-} uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)
src/Test.hs view
@@ -1,5 +1,7 @@ module Main where +import qualified Test.Data.List.Reverse.StrictElement as RevElem+import qualified Test.Data.List.Reverse.StrictSpine as RevSpine import qualified Test.Data.List      as ListHT import qualified Test.Data.ListMatch as ListMatch import qualified Test.Data.Maybe     as MaybeHT@@ -14,6 +16,8 @@ main =    mapM_ (\(msg,io) -> putStr (msg++": ") >> io) $    concat $+      prefix "ReverseSpine" RevSpine.tests :+      prefix "ReverseElem" RevElem.tests :       prefix "List"      ListHT.tests :       prefix "ListMatch" ListMatch.tests :       prefix "Maybe"     MaybeHT.tests :
src/Test/Data/List.hs view
@@ -1,5 +1,6 @@ module Test.Data.List where +import qualified Data.List.Reverse.StrictElement as Rev import qualified Data.List.HT.Private as ListHT import qualified Data.List as List import Control.Monad (liftM2, )@@ -11,13 +12,21 @@   -takeWhileRev :: (Ord a) => (a -> Bool) -> [a] -> Bool-takeWhileRev p xs =-   ListHT.takeWhileRev p xs == reverse (takeWhile p (reverse xs))+takeWhileRev0 :: (Eq a) => (a -> Bool) -> [a] -> Bool+takeWhileRev0 p xs =+   ListHT.takeWhileRev0 p xs == Rev.takeWhile p xs -dropWhileRev :: (Ord a) => (a -> Bool) -> [a] -> Bool+takeWhileRev1 :: (Eq a) => (a -> Bool) -> [a] -> Bool+takeWhileRev1 p xs =+   ListHT.takeWhileRev1 p xs == Rev.takeWhile p xs++takeWhileRev2 :: (Eq a) => (a -> Bool) -> [a] -> Bool+takeWhileRev2 p xs =+   ListHT.takeWhileRev2 p xs == Rev.takeWhile p xs++dropWhileRev :: (Eq a) => (a -> Bool) -> [a] -> Bool dropWhileRev p xs =-   ListHT.dropWhileRev p xs == reverse (dropWhile p (reverse xs))+   ListHT.dropWhileRev p xs == Rev.dropWhile p xs   takeRev :: (Eq a) => Int -> [a] -> Bool@@ -28,7 +37,32 @@ dropRev n xs =    ListHT.dropRev n xs == reverse (drop n (reverse xs)) +splitAtRev :: (Eq a) => Int -> [a] -> Bool+splitAtRev n xs =+   xs == uncurry (++) (ListHT.splitAtRev n xs) ++breakAfterAppend :: (Eq a) => (a -> Bool) -> [a] -> Bool+breakAfterAppend p xs =+   uncurry (++) (ListHT.breakAfter p xs) == xs++breakAfter0 :: (Eq a) => (a -> Bool) -> [a] -> Bool+breakAfter0 p xs =+   ListHT.breakAfterRec p xs == ListHT.breakAfterFoldr p xs++breakAfter1 :: (Eq a) => (a -> Bool) -> [a] -> Bool+breakAfter1 p xs =+   ListHT.breakAfterRec p xs == ListHT.breakAfterBreak p xs++breakAfter2 :: (Eq a) => (a -> Bool) -> [a] -> Bool+breakAfter2 p xs =+   ListHT.breakAfterRec p xs == ListHT.breakAfterTakeUntil p xs++breakAfterUntil :: (Eq a) => (a -> Bool) -> [a] -> Bool+breakAfterUntil p xs =+   ListHT.takeUntil p xs == fst (ListHT.breakAfter p xs)++ sieve :: Eq a => Int -> [a] -> Property sieve n x =    n>0 ==>@@ -84,19 +118,36 @@ mapAdjacent x xs =    ListHT.mapAdjacent subtract (scanl (+) x xs) == xs +mapAdjacentPointfree :: (Num a, Eq a) => [a] -> Bool+mapAdjacentPointfree xs =+   ListHT.mapAdjacent (+) xs == ListHT.mapAdjacentPointfree (+) xs + simple ::    (Testable test) =>    (Int -> [Integer] -> test) -> IO () simple = quickCheck +elemCheck ::+   (Testable test) =>+   (Float -> [Float] -> test) -> IO ()+elemCheck = quickCheck + tests :: [(String, IO ())] tests =-   ("takeWhileRev",     quickCheck (\a -> takeWhileRev ((a::Integer)>=))) :-   ("dropWhileRev",     quickCheck (\a -> dropWhileRev ((a::Integer)>=))) :+   ("takeWhileRev0",    elemCheck (\a -> takeWhileRev0 (a>=))) :+   ("takeWhileRev1",    elemCheck (\a -> takeWhileRev1 (a>=))) :+   ("takeWhileRev2",    elemCheck (\a -> takeWhileRev2 (a>=))) :+   ("dropWhileRev",     elemCheck (\a -> dropWhileRev (a>=))) :    ("takeRev",          simple takeRev) :    ("dropRev",          simple dropRev) :+   ("splitAtRev",       simple splitAtRev) :+   ("breakAfterAppend", elemCheck (\a -> breakAfterAppend (a>=))) :+   ("breakAfter0",      elemCheck (\a -> breakAfter0 (a>=))) :+   ("breakAfter1",      elemCheck (\a -> breakAfter1 (a>=))) :+   ("breakAfter2",      elemCheck (\a -> breakAfter2 (a>=))) :+   ("breakAfterUntil",  elemCheck (\a -> breakAfterUntil (a>=))) :    ("sieve",            simple sieve) :    ("sliceHorizontal",  simple sliceHorizontal) :    ("sliceVertical",    simple sliceVertical) :@@ -105,4 +156,6 @@    ("outerProduct",     quickCheck (outerProduct    :: [Integer] -> [Int] -> Bool)) :    ("iterate",          quickCheck (iterate (+)     :: Integer -> Bool)) :    ("mapAdjacent",      quickCheck (mapAdjacent     :: Integer -> [Integer] -> Bool)) :+   ("mapAdjacentPointfree",+                        quickCheck (mapAdjacentPointfree :: [Integer] -> Bool)) :    []
+ src/Test/Data/List/Reverse/StrictElement.hs view
@@ -0,0 +1,53 @@+module Test.Data.List.Reverse.StrictElement where++import qualified Data.List.Reverse.StrictElement as Rev+import qualified Data.List as List+import Data.Tuple.HT (mapPair, swap, )++import Test.QuickCheck (Testable, quickCheck, )++import Prelude hiding (takeWhile, dropWhile, span, )+++takeWhile :: (Ord a) => (a -> Bool) -> [a] -> Bool+takeWhile p xs =+   Rev.takeWhile p xs == reverse (List.takeWhile p (reverse xs))++dropWhile :: (Ord a) => (a -> Bool) -> [a] -> Bool+dropWhile p xs =+   Rev.dropWhile p xs == reverse (List.dropWhile p (reverse xs))++span :: (Ord a) => (a -> Bool) -> [a] -> Bool+span p xs =+   Rev.span p xs == swap (mapPair (reverse, reverse) (List.span p (reverse xs)))++spanTakeDrop :: (Ord a) => (a -> Bool) -> [a] -> Bool+spanTakeDrop p xs =+   Rev.span p xs == (Rev.dropWhile p xs, Rev.takeWhile p xs)++dropWhileInf :: (Ord a) => a -> [a] -> Bool+dropWhileInf x xs =+   let ys = List.take 1000 $ Rev.dropWhile (x/=) $ cycle $ x:xs+   in  ys==ys++spanInf :: (Ord a) => a -> [a] -> Bool+spanInf x xs =+   let ys = List.take 1000 $ fst $ Rev.span (x/=) $ cycle $ x:xs+   in  ys==ys+++simple ::+   (Testable test) =>+   (Float -> [Float] -> test) -> IO ()+simple = quickCheck+++tests :: [(String, IO ())]+tests =+   ("takeWhile",     simple (\a -> takeWhile (a>=))) :+   ("dropWhile",     simple (\a -> dropWhile (a>=))) :+   ("span",          simple (\a -> span (a>=))) :+   ("spanTakeDrop",  simple (\a -> spanTakeDrop (a>=))) :+   ("dropWhileInf",  simple dropWhileInf) :+   ("spanInf",       simple spanInf) :+   []
+ src/Test/Data/List/Reverse/StrictSpine.hs view
@@ -0,0 +1,62 @@+module Test.Data.List.Reverse.StrictSpine where++import qualified Data.List.Reverse.StrictSpine as Rev+import qualified Data.List.Match as Match+import qualified Data.List as List+import Data.Tuple.HT (mapFst, mapPair, swap, )++import Test.QuickCheck (Testable, quickCheck, )++import Prelude hiding (takeWhile, dropWhile, span, )+++takeWhile :: (Ord a) => (a -> Bool) -> [a] -> Bool+takeWhile p xs =+   Rev.takeWhile p xs == reverse (List.takeWhile p (reverse xs))++dropWhile :: (Ord a) => (a -> Bool) -> [a] -> Bool+dropWhile p xs =+   Rev.dropWhile p xs == reverse (List.dropWhile p (reverse xs))++span :: (Ord a) => (a -> Bool) -> [a] -> Bool+span p xs =+   Rev.span p xs == swap (mapPair (reverse, reverse) (List.span p (reverse xs)))++spanTakeDrop :: (Ord a) => (a -> Bool) -> [a] -> Bool+spanTakeDrop p xs =+   Rev.span p xs == (Rev.dropWhile p xs, Rev.takeWhile p xs)++takeWhileBottom :: (Ord a) => a -> [a] -> [a] -> Bool+takeWhileBottom x xs pad =+   let ys = Rev.takeWhile (x/=) $ Match.replicate pad undefined ++ x:xs+   in  ys==ys++dropWhileBottom :: (Ord a) => a -> [a] -> [a] -> Bool+dropWhileBottom x xs pad =+   let n = length $ Rev.dropWhile (x/=) $ Match.replicate pad undefined ++ x:xs+   in  n==n++spanBottom :: (Ord a) => a -> [a] -> [a] -> Bool+spanBottom x xs pad =+   let (n,ys) =+          mapFst length $ Rev.span (x/=) $+          Match.replicate pad undefined ++ x:xs+   in  n==n && ys==ys+++simple ::+   (Testable test) =>+   (Float -> [Float] -> test) -> IO ()+simple = quickCheck+++tests :: [(String, IO ())]+tests =+   ("takeWhile",     simple (\a -> takeWhile (a>=))) :+   ("dropWhile",     simple (\a -> dropWhile (a>=))) :+   ("span",          simple (\a -> span (a>=))) :+   ("spanTakeDrop",  simple (\a -> spanTakeDrop (a>=))) :+   ("takeWhileBottom", simple takeWhileBottom) :+   ("dropWhileBottom", simple dropWhileBottom) :+   ("spanBottom", simple spanBottom) :+   []
utility-ht.cabal view
@@ -1,5 +1,5 @@ Name:             utility-ht-Version:          0.0.11+Version:          0.0.12 License:          BSD3 License-File:     LICENSE Author:           Henning Thielemann <haskell@henning-thielemann.de>@@ -27,6 +27,7 @@ Tested-With:       GHC==7.0.2, GHC==7.2.2, GHC==7.4.1, GHC==7.8.2 Cabal-Version:     >=1.10 Build-Type:        Simple+Stability:         Stable  -- workaround for Cabal-1.10 Extra-Source-Files:@@ -44,7 +45,7 @@ Source-Repository this   type:     darcs   location: http://code.haskell.org/~thielema/utility/-  tag:      0.0.11+  tag:      0.0.12  Library   Build-Depends:@@ -54,6 +55,7 @@   GHC-Options:      -Wall   Hs-Source-Dirs:   src   Exposed-Modules:+    Data.Bits.HT     Data.Bool.HT     Data.Eq.HT     Data.Function.HT@@ -61,6 +63,8 @@     Data.List.HT     Data.List.Key     Data.List.Match+    Data.List.Reverse.StrictElement+    Data.List.Reverse.StrictSpine     Data.Maybe.HT     Data.Monoid.HT     Data.Ord.HT@@ -70,6 +74,7 @@     Data.Tuple.Lazy     Data.Tuple.Strict     Control.Monad.HT+    Control.Applicative.HT     Control.Functor.HT     Data.Strictness.HT     Text.Read.HT@@ -96,6 +101,8 @@   Other-Modules:     Test.Data.List     Test.Data.ListMatch+    Test.Data.List.Reverse.StrictElement+    Test.Data.List.Reverse.StrictSpine     Test.Data.Maybe     Test.Data.Function     Test.Utility