{-# LANGUAGE UndecidableInstances #-}
module Cooked.Families
(
type (∈),
type (∉),
type (⩀),
type (∪),
type Rev,
type (++),
type RevAux,
type Member,
type NonMember,
HList (..),
hHead,
hTail,
)
where
import Data.Kind
import GHC.TypeLits
type family RevAux (els :: [a]) (done :: [a]) :: [a] where
RevAux '[] done = done
RevAux (x ': xs) done = RevAux xs (x ': done)
type Rev els = RevAux els '[]
type family (++) (els :: [a]) (els' :: [a]) :: [a] where
'[] ++ els' = els'
(x ': xs) ++ els' = (x ': xs ++ els')
type family (∪) (xs :: [a]) (ys :: [a]) :: [a] where
'[] ∪ ys = ys
(x ': xs) ∪ ys = x ': (xs ∪ ys)
type family Member (el :: a) (els :: [a]) (extras :: [a]) :: Constraint where
Member x (x ': xs) _ = ()
Member x (y ': xs) l = Member x xs (y ': l)
Member x '[] l = TypeError ('ShowType x ':<>: 'Text " is not a member of " ':<>: 'ShowType (Rev l))
type (∈) el els = Member el els '[]
type family NonMember (el :: a) (els :: [a]) (extras :: [a]) :: Constraint where
NonMember x '[] _ = ()
NonMember x (x ': xs) extras = TypeError ('ShowType x ':<>: 'Text " is already a member of " ':<>: 'ShowType (Rev extras ++ (x ': xs)))
NonMember x (x' ': xs) extras = NonMember x xs (x' ': extras)
type (∉) el els = NonMember el els '[]
type family (⩀) (els :: [a]) (els' :: [a]) :: Constraint where
'[] ⩀ _ = ()
(x ': xs) ⩀ ys = (x ∉ ys, xs ⩀ ys)
data HList :: [Type] -> Type where
HEmpty :: HList '[]
HCons :: a -> HList l -> HList (a ': l)
hHead :: HList (a ': l) -> a
hHead :: forall a (l :: [*]). HList (a : l) -> a
hHead (HCons a
a HList l
_) = a
a
a
hTail :: HList (a ': l) -> HList l
hTail :: forall a (l :: [*]). HList (a : l) -> HList l
hTail (HCons a
_ HList l
l) = HList l
HList l
l
instance Eq (HList '[]) where
HList '[]
_ == :: HList '[] -> HList '[] -> Bool
== HList '[]
_ = Bool
True
instance (Eq (HList l), Eq a) => Eq (HList (a ': l)) where
HCons a
h HList l
t == :: HList (a : l) -> HList (a : l) -> Bool
== HCons a
h' HList l
t' = a
h a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
a
h' Bool -> Bool -> Bool
&& HList l
t HList l -> HList l -> Bool
forall a. Eq a => a -> a -> Bool
== HList l
HList l
t'
instance Show (HList '[]) where
show :: HList '[] -> String
show HList '[]
_ = String
"[]"
instance (Show (HList l), Show a) => Show (HList (a ': l)) where
show :: HList (a : l) -> String
show (HCons a
h HList l
t) = a -> String
forall a. Show a => a -> String
show a
h String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" : " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> HList l -> String
forall a. Show a => a -> String
show HList l
t