fork download
  1. {-# LANGUAGE ExistentialQuantification,
  2.   DeriveDataTypeable,
  3.   PatternSignatures #-}
  4. import Data.Typeable
  5.  
  6. data SomeTest = forall t . Test t => SomeTest t
  7. deriving Typeable
  8.  
  9. class (Typeable t, Show t) => Test t where
  10. toTest :: t -> SomeTest
  11. fromTest :: SomeTest -> Maybe t
  12. toTest = SomeTest
  13. fromTest (SomeTest t) = cast t
  14.  
  15. instance Test SomeTest where
  16. toTest st = st
  17. fromTest = Just
  18.  
  19. instance Show SomeTest where
  20. show (SomeTest s) = show s
  21.  
  22. instance Test Int where
  23. instance Test Bool where
  24. instance Test Char where
  25.  
  26. data Handler a = forall t . Test t => Handler (t -> a)
  27.  
  28. test :: [Handler a] -> SomeTest -> Maybe a
  29. test handlers t = foldr tryHandler Nothing handlers
  30. where tryHandler (Handler handler) rest
  31. = case fromTest t of
  32. Just t' -> Just $ handler t'
  33. Nothing -> rest
  34.  
  35. main = do
  36. let tests = [toTest (5::Int), toTest False, toTest 'a']
  37. putStr "Try cast to Int: "
  38. print $ (map fromTest tests :: [Maybe Int])
  39. putStr "Try cast to Bool: "
  40. print $ (map fromTest tests :: [Maybe Bool])
  41. let handlers = [Handler (\ (a :: Int) -> "Int: " ++ show a),
  42. Handler (\ (a :: Bool) -> "Bool: " ++ show a)]
  43. putStr "Try execute handlers: "
  44. print $ (map (test handlers) tests)
Success #stdin #stdout 0.01s 3560KB
stdin
Standard input is empty
stdout
Try cast to Int: [Just 5,Nothing,Nothing]
Try cast to Bool: [Nothing,Just False,Nothing]
Try execute handlers: [Just "Int: 5",Just "Bool: False",Nothing]