import Data.Functor.Contravariant

-- newtype Predicate a = Predicate { getPredicate :: a -> Bool }

--instance Contravariant Predicate where
--   contramap f (Predicate p) = Predicate (p . f)
--                                              |   `- First, map the input...
--                                          `----- then apply the predicate.

fb = Predicate (\x -> x > 20)

-- :t contramap
-- contramap :: Contravariant f => (a -> b) -> f b -> f a

-- :t contramap (\x -> x * 2)
-- contramap (\x -> x * 2) :: (Num b, Contravariant f) => f b -> f b

-- :t contramap (\x -> x * 2) a
-- contramap (\x -> x * 2) a :: (Ord b, Num b) => Predicate b

fa = contramap (\x -> x * 2) fb

faComposed = contramap (\x -> x + 5) . contramap (\x -> x * 2) $ fb -- composable



main = do
  print $ getPredicate fa 2 -- Flase
  print $ getPredicate faComposes 6 -- True