module Utils.List where

import qualified Data.List.NonEmpty as Nel

import Data.Foldable    (find)
import Data.List        (groupBy, sortBy)
import Data.Tuple.Extra (first)



safeHead :: [a] -> Maybe a
safeHead :: forall a. [a] -> Maybe a
safeHead = (forall a. NonEmpty a -> a
Nel.head <$>) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Maybe (NonEmpty a)
Nel.nonEmpty

safeLast :: [a] -> Maybe a
safeLast :: forall a. [a] -> Maybe a
safeLast = (forall a. NonEmpty a -> a
Nel.last <$>) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Maybe (NonEmpty a)
Nel.nonEmpty

safeTail :: [a] -> Maybe [a]
safeTail :: forall a. [a] -> Maybe [a]
safeTail = (forall a. NonEmpty a -> [a]
Nel.tail <$>) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Maybe (NonEmpty a)
Nel.nonEmpty

safeInit :: [a] -> Maybe [a]
safeInit :: forall a. [a] -> Maybe [a]
safeInit = (forall a. NonEmpty a -> [a]
Nel.init <$>) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Maybe (NonEmpty a)
Nel.nonEmpty


groupByKey :: Eq b => (a -> b) -> [a] -> [[a]]
groupByKey :: forall b a. Eq b => (a -> b) -> [a] -> [[a]]
groupByKey a -> b
f [a]
x = forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy (\a
a a
b -> a -> b
f a
a forall a. Eq a => a -> a -> Bool
== a -> b
f a
b) [a]
x


groupTuplesByKey :: Eq a => [(a, b)] -> [(a, [b])]
groupTuplesByKey :: forall a b. Eq a => [(a, b)] -> [(a, [b])]
groupTuplesByKey [(a, b)]
x = (\[(a, b)]
a -> (forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall a. [a] -> a
head [(a, b)]
a, forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(a, b)]
a)) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
                        forall b a. Eq b => (a -> b) -> [a] -> [[a]]
groupByKey forall a b. (a, b) -> a
fst [(a, b)]
x


sortByKey :: Ord b => (a -> b) -> [a] -> [a]
sortByKey :: forall b a. Ord b => (a -> b) -> [a] -> [a]
sortByKey a -> b
f [a]
x = forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (\a
a a
b -> a -> b
f a
a forall a. Ord a => a -> a -> Ordering
`compare` a -> b
f a
b) [a]
x


zipWithKey :: Eq a => [(a, b)] ->  [(a, c)] -> [(b, Maybe c)]
zipWithKey :: forall a b c. Eq a => [(a, b)] -> [(a, c)] -> [(b, Maybe c)]
zipWithKey [(a, b)]
x [(a, c)]
y = (\(a, b)
a ->  (forall a b. (a, b) -> b
snd (a, b)
a, forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (\(a, c)
b -> forall a b. (a, b) -> a
fst (a, b)
a forall a. Eq a => a -> a -> Bool
== forall a b. (a, b) -> a
fst (a, c)
b) [(a, c)]
y))) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(a, b)]
x


mergeUnion :: Eq a => [(a, b)] -> [(a, c)] -> [(Maybe b, Maybe c)]
mergeUnion :: forall a b c. Eq a => [(a, b)] -> [(a, c)] -> [(Maybe b, Maybe c)]
mergeUnion [(a, b)]
x [(a, c)]
y =  [(Maybe b, Maybe c)]
a forall a. [a] -> [a] -> [a]
++ [(Maybe b, Maybe c)]
b
  where
    a :: [(Maybe b, Maybe c)]
a = (forall a a' b. (a -> a') -> (a, b) -> (a', b)
first forall a. a -> Maybe a
Just) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a b c. Eq a => [(a, b)] -> [(a, c)] -> [(b, Maybe c)]
zipWithKey [(a, b)]
x [(a, c)]
y
    b :: [(Maybe b, Maybe c)]
b = (forall b a. (b, a) -> (a, b)
tupleReverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a a' b. (a -> a') -> (a, b) -> (a', b)
first forall a. a -> Maybe a
Just)) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a b c. Eq a => [(a, b)] -> [(a, c)] -> [(b, Maybe c)]
zipWithKey [(a, c)]
y [(a, b)]
x


mix :: [a] -> [a] -> [a]
mix :: forall a. [a] -> [a] -> [a]
mix (a
x : [a]
xs) (a
y : [a]
ys) = a
x forall a. a -> [a] -> [a]
: a
y forall a. a -> [a] -> [a]
: forall a. [a] -> [a] -> [a]
mix [a]
xs [a]
ys
mix [] [a]
ys             = [a]
ys
mix [a]
xs []             = [a]
xs


tupleReverse :: (b, a) -> (a, b)
tupleReverse :: forall b a. (b, a) -> (a, b)
tupleReverse (b
x, a
y) = (a
y, b
x)