module Control.Annihilator
( Annihilator(..)
, (<|<)
, aconcat
, amappend
, amconcat
, avoid
)
where
class Annihilator a where
ann :: a
(>|>) :: a -> a -> a
instance Annihilator () where
ann = ()
_ >|> _ = ()
instance Annihilator (Maybe a) where
ann = Nothing
Nothing >|> _ = Nothing
_ >|> Nothing = Nothing
_ >|> a = a
instance Annihilator ([] a) where
ann = []
[] >|> _ = []
_ >|> [] = []
_ >|> a = a
instance (Annihilator a, Annihilator b) => Annihilator (a, b) where
ann = (ann, ann)
(a1, b1) >|> (a2, b2) = (a1 >|> a2, b1 >|> b2)
(<|<) :: Annihilator a => a -> a -> a
(<|<) = flip (>|>)
aconcat :: (Annihilator a, Foldable t) => t a -> a
aconcat as
| null as = ann
| otherwise = foldr1 (>|>) as
amappend :: (Annihilator a, Monoid a) => a -> a -> a
amappend a b = (a >|> b) `mappend` (a <|< b)
amconcat :: (Annihilator a, Monoid a, Foldable t) => t a -> a
amconcat as
| null as = ann
| otherwise = foldr1 amappend as
isAnn :: (Annihilator a, Eq a) => a -> Bool
isAnn = (ann ==)
avoid :: Annihilator a => a -> a
avoid = const ann