-- |
-- Copyright: © 2022–2024 Jonathan Knowles
-- License: Apache-2.0
--
module Internal.Semigroup.Eq
    ( allNonNull
    , allUnique
    , allUniqueNonNull
    )
    where

import Data.List
    ( nub )

import Data.Foldable as F

allNonNull :: (Eq a, Semigroup a, Foldable f) => f a -> Bool
allNonNull :: forall a (f :: * -> *).
(Eq a, Semigroup a, Foldable f) =>
f a -> Bool
allNonNull f a
as = (a -> Bool) -> f a -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
F.all (f a
as f a -> a -> Bool
forall a (f :: * -> *).
(Eq a, Semigroup a, Foldable f) =>
f a -> a -> Bool
`canVerifyNonNull`) f a
as

allUnique :: (Eq a, Foldable f) => f a -> Bool
allUnique :: forall a (f :: * -> *). (Eq a, Foldable f) => f a -> Bool
allUnique f a
as = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([a] -> [a]
forall a. Eq a => [a] -> [a]
nub [a]
xs) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs
  where
    xs :: [a]
xs = f a -> [a]
forall a. f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList f a
as

allUniqueNonNull :: (Eq a, Foldable f, Semigroup a) => f a -> Bool
allUniqueNonNull :: forall a (f :: * -> *).
(Eq a, Foldable f, Semigroup a) =>
f a -> Bool
allUniqueNonNull f a
as = f a -> Bool
forall a (f :: * -> *). (Eq a, Foldable f) => f a -> Bool
allUnique f a
as Bool -> Bool -> Bool
&& f a -> Bool
forall a (f :: * -> *).
(Eq a, Semigroup a, Foldable f) =>
f a -> Bool
allNonNull f a
as

canModify :: (Eq a, Semigroup a) => a -> a -> Bool
a
a canModify :: forall a. (Eq a, Semigroup a) => a -> a -> Bool
`canModify` a
b = Bool -> Bool -> Bool
(||)
    (a
a a -> a -> Bool
forall a. (Eq a, Semigroup a) => a -> a -> Bool
`canModifyL` a
b)
    (a
a a -> a -> Bool
forall a. (Eq a, Semigroup a) => a -> a -> Bool
`canModifyR` a
b)

canModifyL :: (Eq a, Semigroup a) => a -> a -> Bool
a
a canModifyL :: forall a. (Eq a, Semigroup a) => a -> a -> Bool
`canModifyL` a
b = a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
a a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
b

canModifyR :: (Eq a, Semigroup a) => a -> a -> Bool
a
a canModifyR :: forall a. (Eq a, Semigroup a) => a -> a -> Bool
`canModifyR` a
b = a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
b a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
a

canVerifyNonNull :: (Eq a, Semigroup a, Foldable f) => f a -> a -> Bool
canVerifyNonNull :: forall a (f :: * -> *).
(Eq a, Semigroup a, Foldable f) =>
f a -> a -> Bool
canVerifyNonNull f a
as a
a = (a -> Bool) -> f a -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
F.any (a
a a -> a -> Bool
forall a. (Eq a, Semigroup a) => a -> a -> Bool
`canModify`) f a
as