考虑一下这个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代码,它定义了许多这样的功能和义务。)
答案 0 :(得分:4)
在这种情况下,问题不在于Name
与'foo
返回的lookupValueName
不同,但使用'foo
的{{1}}会保留foo
在整个模块的编译过程中活着,而lookupValueName "foo"
没有。然后GHC删除"foo"
的绑定和检查测试之旅。
确实从模块中删除了导出列表,这会保留所有顶级绑定,这会使问题消失。