在给定输入的情况下构造代理类型

时间:2016-04-02 16:10:24

标签: haskell data-kinds

鉴于下面的代码在Data.HashMap中查找类型的类型特定信息,是否可以定义注释中记录的新函数getMapVal2来构建{{1}给出类型的参数?

TypeKey

这只是一个玩具代码,用于在运行时通过{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DataKinds #-} import Data.Monoid ((<>)) import Data.Proxy (Proxy(Proxy)) import GHC.TypeLits (KnownSymbol, Symbol, symbolVal) import qualified Data.HashMap.Strict as Map (HashMap, empty, insert, lookup) import Data.Dynamic import GHC.Generics import Data.Maybe (fromJust, isNothing, maybe) type family TypeKey (a :: *) :: Symbol where TypeKey Int = "int" TypeKey T = "trec" data T = T { aInt :: Int} deriving (Show, Generic, Typeable) extract ::(s ~ TypeKey a, Typeable a, KnownSymbol s) => Maybe Dynamic -> Maybe a extract dyn = if (isNothing dyn) then Nothing else fromDynamic . fromJust $ dyn getMapVal :: (s ~ TypeKey a, Typeable a, KnownSymbol s) => Map.HashMap String Dynamic -> String -> Maybe a getMapVal m k = extract $ Map.lookup k m {-- How do we get the TypeKey lookup for type a? getMapVal2 :: (s ~ TypeKey a, Typeable a, KnownSymbol s) => Map.HashMap String Dynamic -> a -> Maybe a getMapVal2 m ty = extract $ Map.lookup (symbolVal (Proxy :: Proxy (TypeKey ???))) m --} main = do let map = Map.insert (symbolVal (Proxy :: Proxy (TypeKey T))) (toDyn $ T {aInt=5}) Map.empty -- we insert some value in hashmap for type T - it is of same type val = getMapVal map (symbolVal (Proxy :: Proxy (TypeKey T))) :: Maybe T -- now let us retrieve the value in map for Type T. We pass the SymbolVal ourselves --val = getMapVal2 map (T {aInt = 2}) -- now we want to lookup map value given something of a type T. Need getMapVal2 to build symbolval given the input type print $ maybe "" show val -- prints value stored in Hashmap for type T which is: T {aInt=5} 测试传递类型特定的配置到作用于类型类型的多态函数。

1 个答案:

答案 0 :(得分:4)

使用the ScopedTypeVariables extension。这允许您在绑定它们的定义的主体中引用forall - 绑定类型变量。

{-# LANGUAGE ScopedTypeVariables #-}

getMapVal2 :: forall a s. (s ~ TypeKey a, Typeable a, KnownSymbol s) => Map.HashMap String Dynamic -> a -> Maybe a
getMapVal2 m ty = extract $ Map.lookup (symbolVal (Proxy :: Proxy (TypeKey a))) m