on develop-nats help sign in
50 lines 1.3 kB history raw
1{-# LANGUAGE ExplicitForAll #-}
2{-# LANGUAGE KindSignatures #-}
3{-# LANGUAGE PolyKinds #-}
4{-# LANGUAGE ScopedTypeVariables #-}
6module Data.TypeRep.Map
7 ( TypeRepMap (..)
8 , empty
9 , insert
10 , keys
11 , lookup
12 , size
13 ) where
15import Prelude hiding (lookup)
17import Data.Proxy (Proxy (..))
18import Data.Typeable (TypeRep, Typeable, typeRep)
19import GHC.Base (Any)
20import Unsafe.Coerce (unsafeCoerce)
22import qualified Data.Map.Lazy as LMap
24-- | Map-like data structure with types served as the keys.
25newtype TypeRepMap (f :: k -> *) = TypeRepMap
26 { unMap :: LMap.Map TypeRep Any
27 }
29-- | Empty structure.
30empty :: TypeRepMap f
31empty = TypeRepMap mempty
33-- | Inserts the value with its type as a key.
34insert :: forall a f . Typeable a => f a -> TypeRepMap f -> TypeRepMap f
35insert val = TypeRepMap . LMap.insert (typeRep (Proxy :: Proxy a)) (unsafeCoerce val) . unMap
37-- | Looks up the value at the type.
38-- >>> let x = lookup $ insert (11 :: Int) empty
39-- >>> x :: Maybe Int
40-- Just 11
41-- >>> x :: Maybe ()
42-- Nothing
43lookup :: forall a f . Typeable a => TypeRepMap f -> Maybe (f a)
44lookup = fmap unsafeCoerce . LMap.lookup (typeRep (Proxy :: Proxy a)) . unMap
46size :: TypeRepMap f -> Int
47size = LMap.size . unMap
49keys :: TypeRepMap f -> [TypeRep]
50keys = LMap.keys . unMap