module Utils where
import IOExts

findMaybe :: (a -> Maybe b) -> [a] -> Maybe b
findMaybe p [] = Nothing
findMaybe p (x:xs) = 
  maybe (findMaybe p xs) Just $ p x

separate :: (a -> Bool) -> [a] -> [[a]]
separate p s = case dropWhile p s of
                [] -> []
	        s' -> obj: separate p s''
		 where (obj,s'') = break p s'

split :: (a -> Bool) -> [a] -> [[a]]
split p s =
  case dropWhile (not . p) s of
      [] -> []
      (obj:s') -> (obj:o):split p s''
        where (o,s'') = break p s'

splitWith :: (a -> Bool) -> [a] -> [[a]]
splitWith p s =
  case break p s of
    (bef,[]) -> [bef]
    (bef,x:aft) -> bef:splitWith p aft

splitWith' :: (a -> Bool) -> [a] -> [[a]]
splitWith' p s =
  case break p s of
    (bef,[]) -> [bef]
    (bef,x:aft) -> bef:(merge x $ splitWith' p aft)
 where
  merge :: a -> [[a]] -> [[a]]
  merge _ [] = []
  merge x (a:as) = (x:a):as


isPrefix :: String -> String -> Bool
isPrefix s y = s == (take (length s) y)

insertOrd :: (a -> a -> Ordering) -> (a -> a -> a) -> a -> [a] -> [a]
insertOrd _ _ x [] = [x]
insertOrd cmp compose x ys@(y:ys') =
  case cmp x y of 
    GT -> y : insertOrd cmp compose x ys'
    EQ -> compose x y : ys'
    LT -> x : ys


foldl1'           :: (b -> b -> b) -> [b] -> b
foldl1' f  []     = error $ "empty foldl1"
foldl1' f  (x:xs) = foldl' f x xs

foldl'           ::  (a -> b -> a) -> a -> [b] -> a
foldl' f a []     = a
foldl' f a (x:xs) =  ($!) (foldl' f)  (f a x) xs


updtIORef :: IORef a -> (a -> IO a) -> IO ()
updtIORef ref iof = readIORef ref >>= iof >>= writeIORef ref

updIORef :: IORef a -> (a -> a) -> IO ()
updIORef ref f = readIORef ref >>= writeIORef ref . f

maybeDo :: Maybe a -> (a -> IO ()) -> IO ()
maybeDo mb f = maybe (return ()) f mb

deleteUsing :: (a -> Bool) -> [a] -> [a]
deleteUsing p [] = []
deleteUsing p (x:xs) = 
 if p x then xs
 else x:deleteUsing p xs

