module Manatee.Toolkit.General.List where
import Control.Arrow
import Control.Monad
import Data.List
import Data.Maybe
import Data.Monoid
import Manatee.Toolkit.General.Basic
(?!) :: [a] -> Int -> Maybe a
[] ?! _ = Nothing
xs ?! n
| n < 0
= Nothing
| n >= length xs
= Nothing
| otherwise
= listToMaybe . drop n $ xs
intersectEnd :: Ord a => [a] -> [a] -> [a]
intersectEnd xs ys = reverse $ intersectFront (reverse xs) (reverse ys)
intersectFront :: Ord a => [a] -> [a] -> [a]
intersectFront xs ys = [x | (x,y) <- zip xs ys, then takeWhile by x == y]
delay :: Int -> [a] -> [Int]
delay n (_:xs) = n : delay (n + 1) xs
delay _ _ = []
listIndex :: [a] -> [Int]
listIndex = delay 0
pairPred :: [a] -> [(a, Int)]
pairPred xs = zip xs $ listIndex xs
different :: Ord a => [a] -> [a] -> [a]
different (x:xs) (y:ys)
| x == y = different xs ys
| otherwise = x : different xs ys
different [] [] = []
different _ _ = error "different: lists not the same length!"
unlessNull :: [a] -> IO () -> IO ()
unlessNull = unless . null
has :: [a] -> Bool
has = not . null
headM :: Monad m => m [a] -> m a
headM = liftM head
lastM :: Monad m => m [a] -> m a
lastM = liftM last
concatM :: Monad m => m [a] -> m [a] -> m [a]
concatM = liftM2 (++)
replaceAt :: Int -> [a] -> a -> [a]
replaceAt n xs x = take n xs ++ x : drop (n + 1) xs
splitWith :: (a -> Bool) -> [a] -> [[a]]
splitWith _ [] = []
splitWith f xs = fst tuple : splitWith f (dropWhile f $ snd tuple)
where tuple = break f xs
concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]
concatMapM f xs = liftM concat $ forM xs f
findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a)
findM _ [] = return Nothing
findM f (x:xs) = ifM (f x) (return $ Just x) (findM f xs)
apply2M :: Monad m => [a] -> (a -> m b) -> (a -> m c) -> m [(b, c)]
apply2M xs f g = forM xs (\x -> zipM' (f x) (g x))
apply2 :: [a] -> (a -> b) -> (a -> c) -> [(b, c)]
apply2 xs f g = map (f &&& g) xs
partitionM :: Monad m => (a -> m Bool) -> [a] -> m ([a], [a])
partitionM _ [] = return ([], [])
partitionM f (x:xs) =
liftM2 mappend (ifM (f x) (return ([x], [])) (return ([], [x]))) (partitionM f xs)
init_ [] = []
init_ xs = init xs
foldl1_ _ [] = []
foldl1_ f xs = foldl1 f xs
findNext :: (a -> Bool) -> [a] -> Maybe a
findNext x = listToMaybe . drop 1 . dropWhile (not . x)
findNextCycle :: (a -> Bool) -> [a] -> Maybe a
findNextCycle _ [] = Nothing
findNextCycle f list =
case dropWhile (not . f) list of
[] -> Nothing
[_] -> Just $ head list
ls -> listToMaybe $ drop 1 ls
findPrevCycle :: (a -> Bool) -> [a] -> Maybe a
findPrevCycle _ [] = Nothing
findPrevCycle f list
| length dropList == length list
= Nothing
| null dropList
= Just $ last list
| otherwise
= Just $ last dropList
where dropList = takeWhile (not . f) list
deleteAt :: Int -> [a] -> [a]
deleteAt _ [] = []
deleteAt i xs
| i < 0
= []
| i >= length xs
= []
| otherwise
= (\(a, b) -> a ++ tail b) (splitAt i xs)
getLast :: [a] -> Maybe a
getLast [] = Nothing
getLast xs = Just $ last xs
getFirst :: [a] -> Maybe a
getFirst [] = Nothing
getFirst xs = Just $ head xs
zipWithIndex :: [a] -> (a -> Int -> c) -> [c]
zipWithIndex xs f = zipWith f xs [0..]
zipWithIndexM :: Monad m => [a] -> (a -> Int -> m c) -> m [c]
zipWithIndexM xs f = zipWithM f xs [0..]
zipWithIndexM_ :: Monad m => [a] -> (a -> Int -> m c) -> m ()
zipWithIndexM_ xs f = zipWithM_ f xs [0..]
addMap :: ([a] -> [a]) -> [[a]] -> [a]
addMap _ [] = []
addMap _ [x] = x
addMap f xs = concatMap f (init xs) ++ last xs
insertUnique :: Ord a => a -> [a] -> [a]
insertUnique x xs
| x `elem` xs = xs
| otherwise = insert x xs