Skip to content

Instantly share code, notes, and snippets.

@cheecheeo
Last active August 29, 2015 14:06
Show Gist options
  • Save cheecheeo/a37dd840f0356c30a795 to your computer and use it in GitHub Desktop.
Save cheecheeo/a37dd840f0356c30a795 to your computer and use it in GitHub Desktop.
Finding things in a list
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment