module MagicHaskeller.T10 where
import Control.Monad
import Data.List(partition, sortBy)
import Data.Monoid
import Data.Functor((<$>))
liftList :: MonadPlus m => [a] -> m a
liftList = msum . map return
scan10 (xs:xss) = scanl (\x y -> tokoro10 (x ++ y)) (tokoro10 xs) xss
mergesortWithBy :: (k->k->k) -> (k->k->Ordering) -> [k] -> [k]
mergesortWithBy op cmp = mergesortWithByBot op (\x y -> Just (cmp x y))
mergesortWithByBot :: (k->k->k) -> (k -> k -> Maybe Ordering) -> [k] -> [k]
mergesortWithByBot op cmp = mergesortWithByBot' op cmp . map return
mergesortWithByBotIO :: (k->k->k) -> (k -> k -> IO (Maybe Ordering)) -> [k] -> IO [k]
mergesortWithByBotIO op cmp = mergesortWithByBot'IO op cmp . map (:[])
mergesortWithByBot' :: (k->k->k) -> (k -> k -> Maybe Ordering) -> [[k]] -> [k]
mergesortWithByBot' op cmp [] = []
mergesortWithByBot' op cmp [xs] = xs
mergesortWithByBot' op cmp xss = mergesortWithByBot' op cmp (merge_pairsBot op cmp xss)
mergesortWithByBot'IO :: (k->k->k) -> (k -> k -> IO (Maybe Ordering)) -> [[k]] -> IO [k]
mergesortWithByBot'IO op cmp [] = return []
mergesortWithByBot'IO op cmp [xs] = return xs
mergesortWithByBot'IO op cmp xss = mergesortWithByBot'IO op cmp =<< (merge_pairsBotIO op cmp xss)
merge_pairsBot :: (k->k->k) -> (k -> k -> Maybe Ordering) -> [[k]] -> [[k]]
merge_pairsBot op cmp [] = []
merge_pairsBot op cmp [xs] = [xs]
merge_pairsBot op cmp (xs:ys:xss) = mergeWithByBot op cmp xs ys : merge_pairsBot op cmp xss
merge_pairsBotIO :: (k->k->k) -> (k -> k -> IO (Maybe Ordering)) -> [[k]] -> IO [[k]]
merge_pairsBotIO op cmp [] = return []
merge_pairsBotIO op cmp [xs] = return [xs]
merge_pairsBotIO op cmp (xs:ys:xss) = liftM2 (:) (mergeWithByBotIO op cmp xs ys) $ merge_pairsBotIO op cmp xss
mergeWithBy :: (k->k->k) -> (k->k->Ordering) -> [k] -> [k] -> [k]
mergeWithBy op cmp = mergeWithByBot op (\x y -> Just (cmp x y))
mergeWithByBot :: (k->k->k) -> (k -> k -> Maybe Ordering) -> [k] -> [k] -> [k]
mergeWithByBot op cmp xs [] = xs
mergeWithByBot op cmp [] ys = ys
mergeWithByBot op cmp (x:xs) (y:ys)
= case x `cmp` y of
Just GT -> y : mergeWithByBot op cmp (x:xs) ys
Just EQ -> x `op` y : mergeWithByBot op cmp xs ys
Just LT -> x : mergeWithByBot op cmp xs (y:ys)
Nothing -> mergeWithByBot op cmp xs ys
mergeWithByBotIO :: (k->k->k) -> (k -> k -> IO (Maybe Ordering)) -> [k] -> [k] -> IO [k]
mergeWithByBotIO op cmp xs [] = return xs
mergeWithByBotIO op cmp [] ys = return ys
mergeWithByBotIO op cmp (x:xs) (y:ys)
= do mbo <- x `cmp` y
case mbo of
Just GT -> (y :) <$> mergeWithByBotIO op cmp (x:xs) ys
Just EQ -> (x `op` y :) <$> mergeWithByBotIO op cmp xs ys
Just LT -> (x :) <$> mergeWithByBotIO op cmp xs (y:ys)
Nothing -> mergeWithByBotIO op cmp xs ys
diffSortedBy _ [] _ = []
diffSortedBy _ vs [] = vs
diffSortedBy op vs@(c:cs) ws@(d:ds) = case op c d of EQ -> diffSortedBy op cs ds
LT -> c : diffSortedBy op cs ws
GT -> diffSortedBy op vs ds
diffSortedByBot _ [] _ = []
diffSortedByBot _ vs [] = vs
diffSortedByBot op vs@(c:cs) ws@(d:ds) = case op c d of
Just EQ -> diffSortedByBot op cs ds
Just LT -> c : diffSortedByBot op cs ws
Just GT -> diffSortedByBot op vs ds
Nothing -> diffSortedByBot op cs ds
tokoro10nil :: Eq k => [([a],[k],i)] -> [([a],[k],i)]
tokoro10nil xs = case partition (\ (_,k,_) -> k==[] ) xs of
([], diff) -> diff
(same@((_,_,i):_), diff) -> (concat (map (\ (a,_,_) -> a) same), [], i) : diff
tokoro10 :: (Monoid a, Eq k, Ord k) => [(a,k,i)] -> [(a,k,i)]
tokoro10 = mergesortWithBy (\(xs,k,i) (ys,_,_) -> (xs `mappend` ys, k, i)) (\ (_,k,_) (_,l,_) -> k `compare` l)
[] !? n = Nothing
(x:xs) !? 0 = Just x
(x:xs) !? n = xs !? (n1)