{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}
module Data.HTree.Families
  ( All
  , AllC
  , AllInv
  , Both
  , Not
  , Top
  , type (++)
  , type (||)
  )
where
import Data.Kind (Constraint)
type (++) :: forall k. [k] -> [k] -> [k]
type family xs ++ ys where
  '[] ++ ys = ys
  (x : xs) ++ ys = x : xs ++ ys
type (||) :: Bool -> Bool -> Bool
type family a || b where
  'True || b = 'True
  'False || b = b
type AllC :: forall k. (k -> Constraint) -> [k] -> Constraint
class All c xs => AllC c xs
instance All c xs => AllC c xs
type All :: forall k. (k -> Constraint) -> [k] -> Constraint
type family All c xs where
  All c '[] = ()
  All c (x : xs) = (c x, All c xs)
type Top :: k -> Constraint
class Top k
instance Top k
type Not :: Bool -> Bool
type family Not a where
  Not 'True = 'False
  Not 'False = 'True
infixr 5 ++
type AllInv :: [k -> Constraint] -> k -> Constraint
class AllInv l k
instance AllInv '[] k
instance (c k, AllInv cs k) => AllInv (c ': cs) k
type Both :: (k -> Constraint) -> (k -> Constraint) -> k -> Constraint
class (c1 a, c2 a) => Both c1 c2 a
instance (c1 a, c2 a) => Both c1 c2 a