如何在Haskell中将类型转换为字符串?

9

假设我在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等内容,这并不是我想要的。


你想用这个字符串做什么?如果你在代码中使用了错误的类型名称,你的程序应该会给出编译错误。 - Dan Burton
我想要一个类型名称的字符串,而不是类型本身。它用于显示类型名称并将其用于匹配类型名称等。 - mentics
4个回答

11

总之,答案就是启用模板哈斯克尔并使用'''

{-# LANGUAGE TemplateHaskell #-}
main = do
  putStrLn $ show 'read
如果你的类型派生自Typeable(ghc可以自动完成),那么你可以直接从Data.Typeable调用typeOf来获取可显示的表示形式。
如果您想获取某些多态函数的类型,则可以使用Hackage上的polytypeable包: 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提取类型信息是唯一的方法。 请参见reifyInfohttp://hackage.haskell.org/packages/archive/template-haskell/2.5.0.0/doc/html/Language-Haskell-TH.html

GHC手册的7.5.3节记录了这个内容:http://www.haskell.org/ghc/docs/latest/html/users_guide/deriving.html#deriving-typeable - Chris Kuklewicz
@taotree。多态类型的字符串类型是什么?你是指函数签名吗?所以你可以得到 typeStr id = a -> a - sclv
对于造成的困惑我深感抱歉。我已经尝试重申问题以强调我的意图。typeOf 不是我想要的。我想要完全限定名称,而不是类型定义。 - mentics
好的,reify 带我到了 Name,然后带我到了 ',这就是我需要的。 - mentics

4
您无法将theMagic定义为函数(因为它需要一个类型参数),但您可以接近实现它。
import Data.Typeable
...
putStrLn $ show $ typeOf (undefined :: MyType)

3
您可以使用 Proxy 来实现这个功能:
Prelude> import Data.Typeable
Prelude Data.Typeable> show $ typeRep (Proxy :: Proxy [Int])
"[Int]"

0

标准的 Haskell 不支持类型名的此功能;只有对于使用 deriving Show 的函子名称才支持。您可能能够使用 Template Haskell 将类型名称作为字符串获取。


是的,我猜测可能需要模板哈斯克尔。 - mentics

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接