Divisible
class Contravariant f => Divisible f where
divide :: (a -> (b, c)) -> f b -> f c -> f a
conquer :: f a
divided :: Divisible f => f a -> f b -> f (a, b)
divided = divide id
conquered :: Divisible f => f ()
conquered = conquer
Predicate 是个 Divisible
newtype Predicate a = Predicate { getPredicate :: a -> Bool }
instance Divisible Predicate where
divide f (Predicate g) (Predicate h) = Predicate $ a -> case f a of
(b, c) -> g b && h c
conquer = Predicate $ const True
Comparison 是个 Divisible
newtype Comparison a = Comparison { getComparison :: a -> a -> Ordering }
instance Divisible Comparison where
divide f (Comparison g) (Comparison h) = Comparison $ a b -> case f a of
(a',a'') -> case f b of
(b',b'') -> g a' b' `mappend` h a'' b''
conquer = Comparison $ \_ _ -> EQ
应用 Divisible
Prelude Data.Functor.Contravariant Data.Functor.Contravariant.Divisible> getPredicate (divide (x->(x,x)) (Predicate (>3)) (Predicate (<5))) 4
True
Prelude Data.Functor.Contravariant Data.Functor.Contravariant.Divisible> getPredicate conquer 2
True
参考链接
ZuriHac 2015 - Discrimination is Wrong: Improving Productivity