{-# LANGUAGE UndecidableInstances #-}
module Cooked.Skeleton.Families
(
type (∈),
type (∉),
type (⩀),
type (∪),
type Rev,
type (++),
type RevAux,
type Member,
type NonMember,
)
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)