{-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE UndecidableInstances #-} module Data.Type.List ( (:++:), Elem, Intersect, Remove ) where -- generic-labels import Data.Type.Multiplicity ( AddMult , Mult ( None, One ) ) -------------------------------------------------------------------------------- infixr 5 :++: type (:++:) :: [k] -> [k] -> [k] type family xs :++: ys where '[] :++: ys = ys ( x ': xs ) :++: ys = x ': xs :++: ys type Elem :: k -> [k] -> Bool type family Elem x xs where Elem _ '[] = False Elem x ( x ': _ ) = True Elem x ( _ ': ys ) = Elem x ys type Remove :: k -> [k] -> ( [k], Mult ) type family Remove x ys where Remove _ '[] = '( '[], None ) Remove x ( x ': ys ) = RemoveHelper Nothing ( Remove x ys ) Remove x ( y ': ys ) = RemoveHelper ( Just y ) ( Remove x ys ) type RemoveHelper :: Maybe k -> ( [k], Mult ) -> ( [k], Mult ) type family RemoveHelper new rest where RemoveHelper Nothing '( rest, m ) = '( rest, m `AddMult` One ) RemoveHelper ( Just y ) '( rest, m ) = '( y ': rest, m ) -- | Intersect two lists, removing duplicates. type Intersect :: [k] -> [k] -> [k] type family Intersect as bs where Intersect '[] _ = '[] Intersect _ '[] = '[] Intersect ( a ': as ) bs = IntersectHelper a as ( Remove a bs ) type IntersectHelper :: k -> [k] -> ( [k], Mult ) -> [k] type family IntersectHelper a as rem_a_bs where IntersectHelper _ as '( bs, None ) = Intersect as bs IntersectHelper a as '( bs, _ ) = a ': Intersect as bs