module Twee.Utils where
import Control.Arrow((&&&))
import Control.Exception
import Data.List(groupBy, sortBy)
import Data.Ord(comparing)
import System.IO
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)
collate :: Ord a => ([b] -> c) -> [(a, b)] -> [(a, c)]
collate f = map g . partitionBy fst
where
g xs = (fst (head xs), f (map snd xs))
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 = usortBy compare
usortBy :: (a -> a -> Ordering) -> [a] -> [a]
usortBy f = map head . groupBy (\x y -> f x y == EQ) . sortBy f
sortBy' :: Ord b => (a -> b) -> [a] -> [a]
sortBy' f = map snd . sortBy (comparing fst) . map (\x -> (f x, x))
usortBy' :: Ord b => (a -> b) -> [a] -> [a]
usortBy' f = map snd . usortBy (comparing fst) . map (\x -> (f x, x))
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
newtype Max a = Max { getMax :: Maybe a }
getMaxWith :: Ord a => a -> Max a -> a
getMaxWith x (Max (Just y)) = x `max` y
getMaxWith x (Max Nothing) = x
instance Ord a => Monoid (Max a) where
mempty = Max Nothing
Max (Just x) `mappend` y = Max (Just (getMaxWith x y))
Max Nothing `mappend` y = y
newtype Min a = Min { getMin :: Maybe a }
getMinWith :: Ord a => a -> Min a -> a
getMinWith x (Min (Just y)) = x `min` y
getMinWith x (Min Nothing) = x
instance Ord a => Monoid (Min a) where
mempty = Min Nothing
Min (Just x) `mappend` y = Min (Just (getMinWith x y))
Min Nothing `mappend` y = y
labelM :: Monad m => (a -> m b) -> [a] -> m [(a, b)]
labelM f = mapM (\x -> do { y <- f x; return (x, y) })
#if __GLASGOW_HASKELL__ < 710
isSubsequenceOf :: Ord a => [a] -> [a] -> Bool
[] `isSubsequenceOf` ys = True
(x:xs) `isSubsequenceOf` [] = False
(x:xs) `isSubsequenceOf` (y:ys)
| x == y = xs `isSubsequenceOf` ys
| otherwise = (x:xs) `isSubsequenceOf` ys
#endif