Read, conditionally

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{-# LANGUAGE ScopedTypeVariables, ExistentialQuantification #-}

import Data.Typeable
import Data.Maybe

data Dyn = forall a. (Typeable a, Read a) => Read a
         | forall a. Typeable a => NoRead a

class Typeable a => DynC a where
    mk :: a -> Dyn

get :: forall a. DynC a => String -> Maybe a
get xs = case mk wit of
            Read (x :: b) -> cast (read xs :: b)
            _             -> Nothing
 where
    wit :: a
    wit = undefined

instance DynC Int where
    mk = Read

instance (Typeable a, Typeable b) => DynC (a -> b) where
    mk = NoRead

main = do
    print (get "1" :: Maybe Int)
    print . isJust $ (get "id" :: Maybe (Int -> Int))