11

我想用这种类型签名写一个函数:

getTypeRep :: Typeable a => t a -> TypeRep

其中 TypeRep 将是a的类型表示,而不是ta的类型表示。也就是说,编译器应该在任何调用站点 [to getTypeRep ] 自动返回正确的类型表示,这将具有a 的具体类型。

为了添加一些上下文,我想创建一个“动态类型”数据类型,它会记住顶级类型,但不会记住它的参数。例如,我想将MyClass a转换为Dynamic MyClass,上面的函数将用于创建Dynamic MyClass的实例,该实例存储类型参数a的表示形式。

4

3 回答 3

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

有趣的设计。

于 2011-05-08T01:11:18.140 回答
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
于 2011-05-08T02:40:47.723 回答
0

这个函数(现在)存在于Data.Typeable typeRep

于 2016-12-30T04:48:01.727 回答