module Data.List.Match.Private where
import Data.Maybe    (fromJust, isNothing, )
import Data.Maybe.HT (toMaybe, )
import Data.Tuple.HT (mapFst, forcePair, )
import Data.Bool.HT  (if', )
import qualified Data.List as List
import Control.Functor.HT (void, )
import Prelude hiding (take, drop, splitAt, replicate, )
take :: [b] -> [a] -> [a]
take = zipWith (flip const)
drop :: [b] -> [a] -> [a]
drop xs ys0 =
   foldl (\ys _ -> laxTail ys) ys0 xs
dropRec :: [b] -> [a] -> [a]
dropRec (_:xs) (_:ys) = dropRec xs ys
dropRec _ ys = ys
drop0 :: [b] -> [a] -> [a]
drop0 xs ys =
   
   map fromJust (dropWhile isNothing
      (zipWith (toMaybe . null) (iterate laxTail xs) ys))
drop1 :: [b] -> [a] -> [a]
drop1 xs ys =
   map snd (dropWhile (not . null . fst) (zip (iterate laxTail xs) ys))
drop2 :: [b] -> [a] -> [a]
drop2 xs ys =
   snd $ head $
   dropWhile (not . null . fst) $
   zip (iterate laxTail xs) (iterate laxTail ys)
laxTail :: [a] -> [a]
laxTail xt = case xt of [] -> []; _:xs -> xs
laxTail0 :: [a] -> [a]
laxTail0 = List.drop 1
splitAt :: [b] -> [a] -> ([a],[a])
splitAt nt xt =
   forcePair $
   case (nt,xt) of
      (_:ns, x:xs) -> mapFst (x:) $ splitAt ns xs
      (_, xs) -> ([],xs)
takeRev :: [b] -> [a] -> [a]
takeRev ys xs = drop (drop ys xs) xs
dropRev :: [b] -> [a] -> [a]
dropRev ys xs = take (drop ys xs) xs
equalLength :: [a] -> [b] -> Bool
equalLength xs ys =
   void xs == void ys
compareLength :: [a] -> [b] -> Ordering
compareLength xs ys =
   compare (void xs) (void ys)
compareLength0 :: [a] -> [b] -> Ordering
compareLength0 =
   let recourse (_:xs) (_:ys) = recourse xs ys
       recourse []     []     = EQ
       recourse (_:_)  []     = GT
       recourse []     (_:_)  = LT
   in  recourse
compareLength1 :: [a] -> [b] -> Ordering
compareLength1 xs ys =
   compare (length xs) (length ys)
lessOrEqualLength :: [a] -> [b] -> Bool
lessOrEqualLength [] _ = True
lessOrEqualLength _ [] = False
lessOrEqualLength (_:xs) (_:ys) = lessOrEqualLength xs ys
shorterList :: [a] -> [a] -> [a]
shorterList xs ys =
   let useX = lessOrEqualLength xs ys
   in  zipWith (if' useX) xs ys
shorterListEq :: (Eq a) => [a] -> [a] -> [a]
shorterListEq xs ys =
   let useX = lessOrEqualLength xs ys
   in  zipWith (\x y -> if' (x==y || useX) x y) xs ys
replicate :: [a] -> b -> [b]
replicate xs y =
   take xs (repeat y)