-- | Functions for working with lists.
module Utils.Drasil.Lists where

import Data.List

-- | Replaces all elements of a target list that belong to a provided "bad"
--   input list.
replaceAll :: Eq a => [a] -> a -> [a] -> [a]
replaceAll :: [a] -> a -> [a] -> [a]
replaceAll bad :: [a]
bad repl :: a
repl (c :: a
c:cs :: [a]
cs) | a
c a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [a]
bad = a
repl a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a] -> a -> [a] -> [a]
forall a. Eq a => [a] -> a -> [a] -> [a]
replaceAll [a]
bad a
repl [a]
cs
                           | Bool
otherwise    = a
c a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a] -> a -> [a] -> [a]
forall a. Eq a => [a] -> a -> [a] -> [a]
replaceAll [a]
bad a
repl [a]
cs
replaceAll _   _    it :: [a]
it                    = [a]
it

-- | Checks if the first set is a subset of the second.
subsetOf :: Eq a => [a] -> [a] -> Bool
xs :: [a]
xs subsetOf :: [a] -> [a] -> Bool
`subsetOf` ys :: [a]
ys = (a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [a]
ys) [a]
xs

-- | Sort a list, removing all duplicates
nubSort :: Ord a => [a] -> [a]
nubSort :: [a] -> [a]
nubSort = [a] -> [a]
forall a. Eq a => [a] -> [a]
nub ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [a]
forall a. Ord a => [a] -> [a]
sort

-- | Interweaves two lists together @[[a,b,c],[d,e,f]] -> [a,d,b,e,c,f]@.
weave :: [[a]] -> [a]
weave :: [[a]] -> [a]
weave = [[a]] -> [a]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[a]] -> [a]) -> ([[a]] -> [[a]]) -> [[a]] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[a]] -> [[a]]
forall a. [[a]] -> [[a]]
transpose

-- | Fold helper function that applies f to all but the last element, applies g to
-- last element and the accumulator.
foldle :: (a -> a -> a) -> (a -> a -> a) -> a -> [a] -> a
foldle :: (a -> a -> a) -> (a -> a -> a) -> a -> [a] -> a
foldle _ _ z :: a
z []     = a
z
foldle _ g :: a -> a -> a
g z :: a
z [x :: a
x]    = a -> a -> a
g a
z a
x
foldle f :: a -> a -> a
f g :: a -> a -> a
g z :: a
z [x :: a
x,y :: a
y]  = a -> a -> a
g (a -> a -> a
f a
z a
x) a
y
foldle f :: a -> a -> a
f g :: a -> a -> a
g z :: a
z (x :: a
x:xs :: [a]
xs) = (a -> a -> a) -> (a -> a -> a) -> a -> [a] -> a
forall a. (a -> a -> a) -> (a -> a -> a) -> a -> [a] -> a
foldle a -> a -> a
f a -> a -> a
g (a -> a -> a
f a
z a
x) [a]
xs

-- | Fold helper function that applies f to all but last element, applies g to last
-- element and accumulator without starting value, does not work for empty list.
foldle1 :: (a -> a -> a) -> (a -> a -> a) -> [a] -> a
foldle1 :: (a -> a -> a) -> (a -> a -> a) -> [a] -> a
foldle1 _ _ []       = [Char] -> a
forall a. HasCallStack => [Char] -> a
error "foldle1 cannot be used with empty list"
foldle1 _ _ [x :: a
x]      = a
x
foldle1 _ g :: a -> a -> a
g [x :: a
x,y :: a
y]    = a -> a -> a
g a
x a
y
foldle1 f :: a -> a -> a
f g :: a -> a -> a
g (x :: a
x:y :: a
y:xs :: [a]
xs) = (a -> a -> a) -> (a -> a -> a) -> a -> [a] -> a
forall a. (a -> a -> a) -> (a -> a -> a) -> a -> [a] -> a
foldle a -> a -> a
f a -> a -> a
g (a -> a -> a
f a
x a
y) [a]
xs