How to replicate the behaviour of 'name in a TH splice

我们两清 提交于 2019-12-11 04:08:32

问题


Consider this Haskell file:

{-# 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 ()

It uses Template Haskell to define test obligations which are tested by the GHC plugin in inspection-testing.

Under the hood, inspection testing passes a Template Haskell name in an annotation, and converts it to to a Core name using thNameToGhcName, and then tries to find this name in the current module.

This works fine if I create a template Haskell name using 'foo, but it fails if I use lookupValueName.

  • Why are they different?
  • How can I recreate the behavior of 'foo when I have a string?

(Why do I not just use 'foo? Because I want to dynamically create obligations, so I have Template Haskell code that defines many such functions and obligations.)


回答1:


The problem in this case is not so much that the Name returned by 'foo vs. lookupValueName is different, but that using 'foo keeps foo alive throughout the compilation of the module, while lookupValueName "foo" does not. Then GHC removes the binding of "foo" and inspection-testing trips over it.

And indeed removing the export list from the module, which keeps all top-level bindings around, makes the problem go away.



来源:https://stackoverflow.com/questions/50236926/how-to-replicate-the-behaviour-of-name-in-a-th-splice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!