module Data.Monoid.Unique (Unique(..), singletonUnique, allUnique) where
import Data.Foldable (Foldable, toList)
import Data.Monoid (Monoid(..))
import Data.Set (Set)
import qualified Data.Set as Set
data Unique a
= AllUnique (Set a)
| Duplicated a
deriving (Eq, Ord, Show)
singletonUnique :: a -> Unique a
singletonUnique = AllUnique . Set.singleton
instance Ord a => Monoid (Unique a) where
mempty = AllUnique Set.empty
mappend (AllUnique s1) (AllUnique s2) =
let isect = Set.intersection s1 s2
in if Set.null isect
then AllUnique (Set.union s1 s2)
else Duplicated (head $ Set.toList isect)
mappend da@(Duplicated _a) _ = da
mappend _ da@(Duplicated _a) = da
allUnique :: (Ord a, Foldable f) => f a -> Bool
allUnique = allUnique' Set.empty . toList
allUnique' :: Ord a => Set a -> [a] -> Bool
allUnique' _s [] = True
allUnique' s (x:xs) =
if x `Set.member` s
then False
else allUnique' (Set.insert x s) xs