+instance ( ApplyT f x
+ , MapT f xs
+ , List (Map f xs)
+ ) => MapT f (Cons x xs) where
+ type Map f (Cons x xs) = Cons (Apply f x) (Map f xs)
+ hMap f (Cons x xs) = hCons (apply f x) (hMap f xs)
+
+-- All
+type family All f l
+type instance All f Nil = True
+type instance All f (Cons x xs) = If (Apply f x) (All f xs) False
+
+-- Length
+type family Length l
+type instance Length Nil = D0
+type instance Length (Cons e l) = Succ (Length l)
+
+-- Fail
+class Fail a
+
+-- OccursMany (zero or more)
+class OccursMany e l where
+ hOccursMany :: l -> [e]
+
+instance OccursMany e Nil where
+ hOccursMany _ = []
+
+instance ( List l
+ , OccursMany e l
+ )
+ => OccursMany e (Cons e l)
+ where
+ hOccursMany (Cons e l) = e : hOccursMany l
+
+instance ( List l
+ , OccursMany e l
+ )
+ => OccursMany e (Cons e' l)
+ where
+ hOccursMany (Cons _ l) = hOccursMany l
+
+-- OccursMany1 (one or more)
+class OccursMany1 e l where
+ hOccursMany1 :: l -> [e]
+
+instance Fail (TypeNotFound e) => OccursMany1 e Nil where
+ hOccursMany1 _ = undefined
+
+instance ( List l
+ , OccursMany e l
+ )
+ => OccursMany1 e (Cons e l)
+ where
+ hOccursMany1 (Cons e l) = e : hOccursMany l
+
+instance ( List l
+ , OccursMany1 e l
+ )
+ => OccursMany1 e (Cons e' l)
+ where
+ hOccursMany1 (Cons _ l) = hOccursMany1 l
+
+-- OccursOpt (zero or one)
+class OccursOpt e l where
+ hOccursOpt :: l -> Maybe e
+
+instance OccursOpt e Nil where
+ hOccursOpt _ = Nothing
+
+instance OccursNot e l => OccursOpt e (Cons e l) where
+ hOccursOpt (Cons e _) = Just e
+
+instance OccursOpt e l => OccursOpt e (Cons e' l) where
+ hOccursOpt (Cons _ l) = hOccursOpt l
+
+-- Occurs (one)
+class Occurs e l where
+ hOccurs :: l -> e
+
+data TypeNotFound e
+
+instance Fail (TypeNotFound e) => Occurs e Nil
+ where
+ hOccurs = undefined
+
+instance ( List l
+ , OccursNot e l
+ )
+ => Occurs e (Cons e l)
+ where
+ hOccurs (Cons e _) = e
+
+instance ( List l
+ , Occurs e l
+ )
+ => Occurs e (Cons e' l)
+ where
+ hOccurs (Cons _ l) = hOccurs l
+
+-- OccursNot (zero)
+data TypeFound e
+class OccursNot e l
+instance OccursNot e Nil
+instance Fail (TypeFound e) => OccursNot e (Cons e l)
+instance OccursNot e l => OccursNot e (Cons e' l)
+
+-- NoDuplicates
+class NoDuplicates l
+instance NoDuplicates Nil
+instance OccursNot e l => NoDuplicates (Cons e l)
+
+{-
+{-
+"Strongly Typed Heterogeneous Collections"
+ — August 26, 2004
+ Oleg Kiselyov
+ Ralf Lämmel
+ Keean Schupke
+==========================
+9 By chance or by design?
+
+We will now discuss the issues surrounding the definition of type
+equality, inequality, and unification — and give implementations
+differing in simplicity, genericity, and portability.
+
+We define the class TypeEq x y b for type equality. The class relates
+two types x and y to the type HTrue in case the two types are equal;
+otherwise, the types are related to HFalse. We should point out
+however groundness issues. If TypeEq is to return HTrue, the types
+must be ground; TypeEq can return HFalse even for unground types,
+provided they are instantiated enough to determine that they are not
+equal. So, TypeEq is total for ground types, and partial for unground
+types. We also define the class TypeCast x y: a constraint that holds
+only if the two types x and y are unifiable. Regarding groundness of x
+and y, the class TypeCast is less restricted than TypeEq. That is,
+TypeCast x y succeeds even for unground types x and y in case they can
+be made equal through unification. TypeEq and TypeCast are related to
+each other as fol- lows. Whenever TypeEq succeeds with HTrue, TypeCast
+succeeds as well. Whenever TypeEq succeeds with HFalse, TypeCast
+fails. But for unground types, when TypeCast succeeds, TypeEq might
+fail. So the two complement each other for unground types. Also,
+TypeEq is a partial predicate, while TypeCast is a relation. That’s
+why both are useful.
+ -}
+class TypeEq x y b | x y -> b
+instance TypeEq x x True
+instance TypeCast False b =>
+ TypeEq x y b
+
+class TypeCast a b | a -> b, b -> a
+ where
+ typeCast :: a -> b
+
+class TypeCast' t a b | t a -> b, t b -> a
+ where
+ typeCast' :: t -> a -> b
+
+class TypeCast'' t a b | t a -> b, t b -> a
+ where
+ typeCast'' :: t -> a -> b
+
+instance TypeCast' () a b => TypeCast a b
+ where
+ typeCast x = typeCast' () x
+
+instance TypeCast'' t a b => TypeCast' t a b
+ where
+ typeCast' = typeCast''
+
+instance TypeCast'' () a a
+ where
+ typeCast'' _ x = x
+
+
+class MemberT e l where
+ type Member e l
+
+instance MemberT e Nil where
+ type Member e Nil = False
+
+instance MemberT e (Cons e' l) where
+ type Member e (Cons e' l) = TypeEq e e' b => b
+-}
\ No newline at end of file