在Haskell中输入类型名称的String

时间:2011-03-18 15:45:10

标签: haskell introspection

假设我在模块My.Module中定义了MyType类型。我想要字符串“My.Module.MyType”(或类似的东西)。如果我只是直接输入字符串,我可能会输入错误,如果模块或类型名称发生变化,我想在编译时知道。

啊,似乎可能会对我要问的内容感到困惑。请仔细看看这个问题。鉴于代码:

module My.Module
type MyType = Int
data MyType2 = MyConstructor2 Int
main = do
  putStrLn $ theMagic MyType
  putStrLn $ theMagic MyType2

我想要的输出是:

My.Module.MyType
My.Module.MyType2

我正在寻找类型名称,而不是类型定义。 typeOf会输出Int等等,这不是我想要的。

4 个答案:

答案 0 :(得分:9)

总之,答案是启用模板haskell并使用'和''

{-# LANGUAGE TemplateHaskell #-}
main = do
  putStrLn $ show 'read

如果您的类型派生Typeable(ghc可以自动执行),那么您只需从typeOf调用Data.Typeable即可获得可展示的代表。

如果您想获取某些多态函数的类型,Hackage上的多类型包允许您这样做:http://hackage.haskell.org/packages/archive/polytypeable/0.1.0.0/doc/html/Data-PolyTypeable.html

这是一种疯狂的类型级别的东西,由Oleg编写并由Lennart打包,请注意。它有......怪癖。最明显的是它无法给你(我也无法想象任何事情可以坦率地说)类约束上下文。因此,show会被赋予a -> String而不是forall a. Show a => a -> String的类型。

如果你需要更多,并且只对编译时做某些事情感到满意,那么使用模板haskell直接从ghc中提取类型信息是唯一的方法。请参阅reifyInfo,特别是:http://hackage.haskell.org/packages/archive/template-haskell/2.5.0.0/doc/html/Language-Haskell-TH.html

答案 1 :(得分:2)

您可以为此使用Proxy

Prelude> import Data.Typeable
Prelude Data.Typeable> show $ typeRep (Proxy :: Proxy [Int])
"[Int]"

答案 2 :(得分:1)

你不能将魔法定义为一个函数(因为它需要一个类型参数),但你可以接近。

import Data.Typeable
...
putStrLn $ show $ typeOf (undefined :: MyType)

答案 3 :(得分:0)

标准Haskell不支持类型名称;仅适用于deriving Show的仿函数名称。您可以使用Template Haskell将类型名称作为字符串获取。