@@ -12,7 +12,9 @@ module TypeFun.Data.List
1212 -- * Elements lookup
1313 , IndexOf
1414 , IndexOf'
15+ , IndicesOf
1516 , Index
17+ , Indices
1618 , Elem
1719 , NotElem
1820 , Count
@@ -22,6 +24,9 @@ module TypeFun.Data.List
2224 , IsPrefixOf
2325 , IsNotPrefixOf
2426 , IsPrefixOfBool
27+ , Union
28+ , AppendUniq
29+ , Intersect
2530 -- * Uniqueness checking
2631 , ElementIsUniq
2732 , UniqElements
@@ -85,11 +90,19 @@ type family IndexOf' (acc :: N) (a :: k) (s :: [k]) :: Maybe N where
8590 IndexOf' acc a (a ': as) = 'Just acc
8691 IndexOf' acc a (b ': as) = IndexOf' (S acc) a as
8792
93+type family IndicesOf (a :: [k]) (b :: [k]) :: [Maybe N] where
94+ IndicesOf '[] bs = '[]
95+ IndicesOf (a ': as) bs = (IndexOf a bs) ': (IndicesOf as bs)
96+
8897type family Index (idx :: N) (s :: [k]) :: Maybe k where
8998 Index idx '[] = 'Nothing
9099 Index Z (a ': as) = 'Just a
91100 Index (S idx) (a ': as) = Index idx as
92101
102+type family Indices (idxs :: [N]) (a :: [k]) :: [Maybe k] where
103+ Indices '[] as = '[]
104+ Indices (i ': idxs) as = (Index i as) ': (Indices idxs as)
105+
93106
94107-- | Generates unresolvable constraint if fists element is not
95108-- contained inside of second
@@ -131,12 +144,27 @@ type family IsPrefixOfBool (a :: [k]) (b :: [k]) :: Bool where
131144 IsPrefixOfBool (a ': as) (a ': bs) = IsPrefixOfBool as bs
132145 IsPrefixOfBool as bs = 'False
133146
147+-- | Appends elements from first list to second if they are not
148+-- presented in.
149+type family Union (a :: [k]) (b :: [k]) :: [k] where
150+ Union '[] bs = bs
151+ Union (a ': as) bs = Union as (AppendUniq a bs)
152+
153+-- | Append element to list if element is not already presented in
154+type family AppendUniq (a :: k) (s :: [k]) :: [k] where
155+ AppendUniq a (a ': bs) = a ': bs
156+ AppendUniq a (b ': bs) = b ': (AppendUniq a bs)
157+ AppendUniq a '[] = '[a]
158+
159+-- | Calculates intersection between two lists. Order of elements is
160+-- taken from first list
161+type Intersect a b = (CatMaybes (Indices (CatMaybes (IndicesOf a b)) b))
162+
134163-- | Checks that element 'a' occurs in a list just once
135164type ElementIsUniq a s = If (Equal (S Z) (Count a s))
136165 (() :: Constraint)
137166 (ElementIsNotUniqInList a s)
138167
139−
140168-- | Checks that all elements in list are unique
141169type UniqElements a = UniqElements' a a
142170