{-# LANGUAGE ExplicitForAll #-}

module Hextra.List where

import Hextra.Conditional
import Data.List

index :: forall n a. Integral n => [a] -> [(n, a)]
index :: [a] -> [(n, a)]
index = n -> [a] -> [(n, a)]
forall t b. Enum t => t -> [b] -> [(t, b)]
index' n
0
  where
    index' :: t -> [b] -> [(t, b)]
index' t
_ [] = []
    index' t
n (b
x:[b]
xs) = (t
n, b
x) (t, b) -> [(t, b)] -> [(t, b)]
forall a. a -> [a] -> [a]
: t -> [b] -> [(t, b)]
index' (t -> t
forall a. Enum a => a -> a
succ t
n) [b]
xs

replaceIndex :: forall n a. Integral n => n -> a -> [a] -> [a]
replaceIndex :: n -> a -> [a] -> [a]
replaceIndex n
a = n -> (a -> a) -> [a] -> [a]
forall n a. Integral n => n -> (a -> a) -> [a] -> [a]
modifyIndex n
a ((a -> a) -> [a] -> [a]) -> (a -> a -> a) -> a -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a -> a
forall a b. a -> b -> a
const

replaceItem :: forall a. Eq a => a -> a -> [a] -> [a]
replaceItem :: a -> a -> [a] -> [a]
replaceItem a
a a
b = (a -> a -> a -> a
forall a. Eq a => a -> a -> a -> a
replace a
a a
b (a -> a) -> [a] -> [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)

modifyIndex :: forall n a. Integral n => n -> (a -> a) -> [a] -> [a]
modifyIndex :: n -> (a -> a) -> [a] -> [a]
modifyIndex n
_ a -> a
_ [] = []
modifyIndex n
0 a -> a
f (a
x:[a]
xs) = a -> a
f a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
xs
modifyIndex n
n a -> a
f l :: [a]
l@(a
x:[a]
xs)
    | n
n n -> n -> Bool
forall a. Ord a => a -> a -> Bool
<= n
0 = [a]
l
    | Bool
True = a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: n -> (a -> a) -> [a] -> [a]
forall n a. Integral n => n -> (a -> a) -> [a] -> [a]
modifyIndex (n -> n
forall a. Enum a => a -> a
pred n
n) a -> a
f [a]
xs

modifyItemIf :: forall a. (a -> Bool) -> (a -> a) -> [a] -> [a]
modifyItemIf :: (a -> Bool) -> (a -> a) -> [a] -> [a]
modifyItemIf a -> Bool
p a -> a
f = ((a -> Bool) -> (a -> a) -> a -> a
forall a. (a -> Bool) -> (a -> a) -> a -> a
applyIf a -> Bool
p a -> a
f (a -> a) -> [a] -> [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)

replaceFromIndex :: forall n a. Integral n => n -> [a] -> [a] -> [a]
replaceFromIndex :: n -> [a] -> [a] -> [a]
replaceFromIndex n
_ [a]
__ [] = []
replaceFromIndex n
n [a]
ys (a
x:[a]
xs)
    | n
n n -> n -> Bool
forall a. Ord a => a -> a -> Bool
<= n
0 = [a]
ys
    | Bool
True = a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: n -> [a] -> [a] -> [a]
forall n a. Integral n => n -> [a] -> [a] -> [a]
replaceFromIndex (n -> n
forall a. Enum a => a -> a
pred n
n) [a]
ys [a]
xs

replaceFromWhen :: forall a. (a -> Bool) -> [a] -> [a] -> [a]
replaceFromWhen :: (a -> Bool) -> [a] -> [a] -> [a]
replaceFromWhen a -> Bool
_ [a]
__ [] = []
replaceFromWhen a -> Bool
p [a]
ys (a
x:[a]
xs)
    | a -> Bool
p a
x = [a]
ys
    | Bool
True = a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: (a -> Bool) -> [a] -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a] -> [a]
replaceFromWhen a -> Bool
p [a]
ys [a]
xs

replaceUpTo :: forall n a. Integral n => n -> [a] -> [a] -> [a]
replaceUpTo :: n -> [a] -> [a] -> [a]
replaceUpTo n
n [a]
ys [a]
xs = [a]
ys [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ n -> [a] -> [a]
forall i a. Integral i => i -> [a] -> [a]
genericDrop n
n [a]
xs

replaceUntil :: forall a. (a -> Bool) -> [a] -> [a] -> [a]
replaceUntil :: (a -> Bool) -> [a] -> [a] -> [a]
replaceUntil a -> Bool
p [a]
ys [a]
xs = [a]
ys [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ (a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
dropUntil a -> Bool
p [a]
xs

takeUntil :: forall a. (a -> Bool) -> [a] -> [a]
takeUntil :: (a -> Bool) -> [a] -> [a]
takeUntil = (a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile ((a -> Bool) -> [a] -> [a])
-> ((a -> Bool) -> a -> Bool) -> (a -> Bool) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Bool
not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.)

dropUntil :: forall a. (a -> Bool) -> [a] -> [a]
dropUntil :: (a -> Bool) -> [a] -> [a]
dropUntil = (a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
dropWhile ((a -> Bool) -> [a] -> [a])
-> ((a -> Bool) -> a -> Bool) -> (a -> Bool) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Bool
not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.)

-- TODO replaceUntil functions

safeHead :: forall a. [a] -> Maybe a
safeHead :: [a] -> Maybe a
safeHead []    = Maybe a
forall a. Maybe a
Nothing
safeHead (a
x:[a]
_) = a -> Maybe a
forall a. a -> Maybe a
Just a
x

safeTail :: forall a. [a] -> Maybe [a]
safeTail :: [a] -> Maybe [a]
safeTail []     = Maybe [a]
forall a. Maybe a
Nothing
safeTail (a
_:[a]
xs) = [a] -> Maybe [a]
forall a. a -> Maybe a
Just [a]
xs

safeLast :: forall a. [a] -> Maybe a
safeLast :: [a] -> Maybe a
safeLast []     = Maybe a
forall a. Maybe a
Nothing
safeLast (a
x:[]) = a -> Maybe a
forall a. a -> Maybe a
Just a
x
safeLast (a
_:[a]
xs) = [a] -> Maybe a
forall a. [a] -> Maybe a
safeLast [a]
xs

safeInit :: forall a. [a] -> Maybe [a]
safeInit :: [a] -> Maybe [a]
safeInit []     = Maybe [a]
forall a. Maybe a
Nothing
safeInit (a
_:[]) = [a] -> Maybe [a]
forall a. a -> Maybe a
Just []
safeInit (a
x:[a]
xs) = (a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
:) ([a] -> [a]) -> Maybe [a] -> Maybe [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a] -> Maybe [a]
forall a. [a] -> Maybe [a]
safeInit [a]
xs

(!!?) :: forall a i. Integral i => [a] -> i -> Maybe a
[] !!? :: [a] -> i -> Maybe a
!!? i
_     = Maybe a
forall a. Maybe a
Nothing
(a
x:[a]
_) !!? i
0  = a -> Maybe a
forall a. a -> Maybe a
Just a
x
(a
_:[a]
xs) !!? i
n = [a]
xs [a] -> i -> Maybe a
forall a i. Integral i => [a] -> i -> Maybe a
!!? (i
n i -> i -> i
forall a. Num a => a -> a -> a
- i
1)

safeCycle :: forall a. a -> [a] -> [a]
safeCycle :: a -> [a] -> [a]
safeCycle a
a [] = a -> [a]
forall a. a -> [a]
repeat a
a
safeCycle a
a [a]
l  = a
a a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
l [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ a -> [a] -> [a]
forall a. a -> [a] -> [a]
safeCycle a
a [a]
l