{-# LANGUAGE ExistentialQuantification, DeriveDataTypeable, PatternSignatures #-} import Data.Typeable data SomeTest = forall t . Test t => SomeTest t deriving Typeable class (Typeable t, Show t) => Test t where toTest :: t -> SomeTest fromTest :: SomeTest -> Maybe t toTest = SomeTest fromTest (SomeTest t) = cast t instance Test SomeTest where toTest st = st fromTest = Just instance Show SomeTest where show (SomeTest s) = show s instance Test Int where instance Test Bool where instance Test Char where data Handler a = forall t . Test t => Handler (t -> a) test :: [Handler a] -> SomeTest -> Maybe a test handlers t = foldr tryHandler Nothing handlers where tryHandler (Handler handler) rest = case fromTest t of Just t' -> Just $ handler t' Nothing -> rest main = do let tests = [toTest (5::Int), toTest False, toTest 'a'] putStr "Try cast to Int: " print $ (map fromTest tests :: [Maybe Int]) putStr "Try cast to Bool: " print $ (map fromTest tests :: [Maybe Bool]) let handlers = [Handler (\ (a :: Int) -> "Int: " ++ show a), Handler (\ (a :: Bool) -> "Bool: " ++ show a)] putStr "Try execute handlers: " print $ (map (test handlers) tests)