{-# LANGUAGE PolyKinds, ConstraintKinds, TypeOperators, MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
-- | This module contains a type-level combinator for combining constraint constructors.
--
-- This is useful because you can't otherwise write an @'Exists'@ type or @'Existential'@ instance referencing more than one at the same time.
module Control.Constraint.Combine where
import Data.Exists.Internal -- just for haddock
-- | Combine two constraint constructors of kind @χ -> 'Constraint'@, where @χ@ is any kind.
--
-- This is the same as
--
-- > type (c :&: d) a = (c a, d a)
--
-- except that it can be partially applied.
--
-- > f :: ((Eq :&: Enum :&: Bounded) a) => a -> Bool
--
-- is equivalent to
--
-- > f :: (Eq a, Enum a, Bounded a) => a -> Bool
class (c a, d a) => (c :&: d) a
instance (c a, d a) => (c :&: d) a
infixl 7 :&:
-- | The same as @':&:'@.
type c `And` d = c :&: d
infixl 7 `And`
-- | An empty constraint, which implies nothing.
--
-- @':&:'@ and @'Empty'@ form a type-level monoid with @'Empty'@ as the identity element.
class Empty a
instance Empty a