如何在TH拼接中复制&name;的名称行为

时间:2018-05-08 15:13:16

标签: haskell ghc template-haskell

考虑一下这个Haskell文件:

{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
module Text (main) where

import Test.Inspection

import Data.Text as T
import Data.Text.Encoding as E
import Data.ByteString (ByteString)

import Language.Haskell.TH

toUpperString :: String -> String
toUpperString = T.unpack . T.toUpper . T.pack

toUpperBytestring :: ByteString -> String
toUpperBytestring = T.unpack . T.toUpper . E.decodeUtf8

do Just n <- lookupValueName "toUpperString"
   inspect $ n `hasNoType` ''T.Text
inspect $ 'toUpperBytestring `hasNoType` ''T.Text

main :: IO ()
main = return ()

它使用模板Haskell来定义测试义务,这些测试义务由GHC插件在检查测试中测试。

在底层,检查测试在注释中传递Template Haskell名称,并使用thNameToGhcName将其转换为Core名称,然后尝试在当前模块中找到此名称。

如果我使用'foo创建模板Haskell名称,这样可以正常工作,但如果我使用lookupValueName则会失败。

  • 为什么他们不一样?
  • 当我有字符串时,如何重新创建'foo的行为?

(为什么我不只是使用'foo?因为我想动态创建义务,所以我有模板Haskell代码,它定义了许多这样的功能和义务。)

1 个答案:

答案 0 :(得分:4)

在这种情况下,问题不在于Name'foo返回的lookupValueName不同,但使用'foo的{​​{1}}会保留foo在整个模块的编译过程中活着,而lookupValueName "foo"没有。然后GHC删除"foo"的绑定和检查测试之旅。

确实从模块中删除了导出列表,这会保留所有顶级绑定,这会使问题消失。

相关问题