我想用这种类型的签名编写一个函数:
getTypeRep :: Typeable a => t a -> TypeRep
其中TypeRep将是 a 的类型表示,而不是 t a 的类型表示。也就是说,编译器应该在任何调用站点[到 getTypeRep ]自动返回正确的类型表示,这将具有 a 的具体类型。
要添加一些上下文,我想创建一个“动态类型”数据类型,其中包含它将记住顶级类型但不记住其参数的扭曲。例如,我想将 MyClass a 转换为 Dynamic MyClass ,上面的函数将用于创建存储a的 Dynamic MyClass 的实例表示类型参数 a 。
答案 0 :(得分:9)
那么,如何使用范围类型变量来选择内部组件:
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Dynamic
import Data.Typeable
getTypeRep :: forall t a . Typeable a => t a -> TypeRep
getTypeRep _ = typeOf (undefined :: a)
适合我:
*Main> getTypeRep (Just ())
()
*Main> getTypeRep (Just 7)
Integer
*Main> getTypeRep ([True])
Bool
有趣的设计。
答案 1 :(得分:8)
在Don解决方案的相关说明中,请注意代码很少需要 ScopedTypeVariables。它只是使解决方案更清洁(但不太便携)。没有作用域类型的解决方案是:
{-# LANGUAGE ExplicitForAll #-}
import Data.Typeable
helper :: t a -> a
helper _ = undefined
getTypeRep :: forall t a. Typeable a => t a -> TypeRep
getTypeRep = typeOf . helper
答案 2 :(得分:0)
此功能(现在)存在于Data.Typeable
typeRep