-- |
-- Copyright: © 2022–2023 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 = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
F.all (f a
as 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 = forall (t :: * -> *) a. Foldable t => t a -> Int
length (forall a. Eq a => [a] -> [a]
nub [a]
xs) forall a. Eq a => a -> a -> Bool
== forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs
  where
    xs :: [a]
xs = 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 = forall a (f :: * -> *). (Eq a, Foldable f) => f a -> Bool
allUnique f a
as Bool -> Bool -> 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 forall a. (Eq a, Semigroup a) => a -> a -> Bool
`canModifyL` a
b)
    (a
a 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 forall a. Eq a => a -> a -> Bool
/= 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 forall a. Eq a => a -> a -> Bool
/= a
b 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 = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
F.any (a
a forall a. (Eq a, Semigroup a) => a -> a -> Bool
`canModify`) f a
as