module FoundIt (FoundIt.elem) where import Data.Semigroup import Data.List.NonEmpty (NonEmpty(..)) data FoundIt a = FoundIt (a -> Bool) a instance (Eq a) => Eq (FoundIt a) where f1 == f2 = case (f1, f2) of (FoundIt _ x1, FoundIt _ x2) -> x1 == x2 && getFoundIt f1 == getFoundIt f2 mkFoundItTriplet :: (Eq a) => a -> a -> a -> a -> (FoundIt a, FoundIt a, FoundIt a) mkFoundItTriplet a x y z = (FoundIt (== a) x, FoundIt (== a) y, FoundIt (== a) z) -- | @FoundIt a@ is a semigroup -- -- prop> \a b c -> let (x, y, z) = mkFoundItTriplet a a b c in x <> (y <> z) == (x <> y) <> (z :: FoundIt Integer) -- prop> \a b c -> let (x, y, z) = mkFoundItTriplet b a b c in x <> (y <> z) == (x <> y) <> (z :: FoundIt Integer) -- prop> \a b c -> let (x, y, z) = mkFoundItTriplet c a b c in x <> (y <> z) == (x <> y) <> (z :: FoundIt Integer) -- prop> \a b c d -> let (x, y, z) = mkFoundItTriplet d a b c in x <> (y <> z) == (x <> y) <> (z :: FoundIt Integer) instance Semigroup (FoundIt a) where f1 <> f2 = if getFoundIt f1 then f1 else f2 getFoundIt :: FoundIt a -> Bool getFoundIt f = case f of FoundIt p x -> p x -- | Is @findMe@ an element of @xs'@? -- >>> FoundIt.elem 5 $ [1..10] -- True -- >>> FoundIt.elem 5 $ [1..4] -- False -- >>> FoundIt.elem 42 $ [1..4] -- False -- >>> FoundIt.elem 42 $ [42] -- True elem :: (Eq a) => a -> [a] -> Bool elem findMe xs' = case xs' of [] -> False (x:xs) -> getFoundIt . sconcat . fmap (FoundIt (== findMe)) $ x :| xs