-- | Miscellaneous utility functions. module Test.QuickSpec.Utils where import Control.Arrow((&&&)) import Data.List(groupBy, sortBy, group, sort) import Data.Ord(comparing) import System.IO import Control.Exception import Control.Spoon repeatM :: Monad m => m a -> m [a] repeatM = sequence . repeat partitionBy :: Ord b => (a -> b) -> [a] -> [[a]] partitionBy value = map (map fst) . groupBy (\x y -> snd x == snd y) . sortBy (comparing snd) . map (id &&& value) isSorted :: Ord a => [a] -> Bool isSorted xs = and (zipWith (<=) xs (tail xs)) isSortedBy :: Ord b => (a -> b) -> [a] -> Bool isSortedBy f xs = isSorted (map f xs) usort :: Ord a => [a] -> [a] usort = map head . group . sort merge :: Ord b => (a -> a -> a) -> (a -> b) -> [a] -> [a] -> [a] merge f c = aux where aux [] ys = ys aux xs [] = xs aux (x:xs) (y:ys) = case comparing c x y of LT -> x:aux xs (y:ys) GT -> y:aux (x:xs) ys EQ -> f x y:aux xs ys orElse :: Ordering -> Ordering -> Ordering EQ `orElse` x = x x `orElse` _ = x unbuffered :: IO a -> IO a unbuffered x = do buf <- hGetBuffering stdout bracket_ (hSetBuffering stdout NoBuffering) (hSetBuffering stdout buf) x spoony :: Eq a => a -> Maybe a spoony x = teaspoon ((x == x) `seq` x)