{-# OPTIONS -fglasgow-exts #-}
{-# LANGUAGE OverlappingInstances, UndecidableInstances #-}
module GetC (tests) where
import Test.HUnit
import Data.Typeable
import Data.Generics
data T1 = T1a Int String | T1b String Int deriving (Typeable, Data)
data T2 = T2a Int Int | T2b String String deriving (Typeable, Data)
data T3 = T3! Int deriving (Typeable, Data)
tests = show [ isC T1a (T1a 1 "foo")
, isC T1a (T1b "foo" 1)
, isC T3 (T3 42)]
~=? output
output = show [True,False,True]
isC :: (Data a, GetT f a, GetC f) => f -> a -> Bool
isC f t = maybe False ((==) (toConstr t)) con
where
kids = gmapQ ExTypeable t
con = getC f kids
data ExTypeable = forall a. Typeable a => ExTypeable a
unExTypeable (ExTypeable a) = cast a
class GetT f t | f -> t
instance GetT g t => GetT (x -> g) t
instance TypeUnify t t' => GetT t t'
class GetC f
where
getC :: f -> [ExTypeable] -> Maybe Constr
instance (Typeable x, GetC g) => GetC (x -> g)
where
getC _ [] = Nothing
getC (f::x->g) (h:t)
=
do
(x::x) <- unExTypeable h
getC (f x) t
instance Data t => GetC t
where
getC y [] = Just $ toConstr y
getC _ (_:_) = Nothing
class TypeUnify a b | a -> b, b -> a
class TypeUnify' x a b | x a -> b, x b -> a
class TypeUnify'' x a b | x a -> b, x b -> a
instance TypeUnify' () a b => TypeUnify a b
instance TypeUnify'' x a b => TypeUnify' x a b
instance TypeUnify'' () a a