找不到变量的接口文件声明

Can't find inerface-file declaration for variable

我正在尝试将一些代码的执行转移到 GHC 8 的编译时间,并且 template-haskel-2.11。代码如下所示:

myThHelper :: FilePath -> Q Exp
myThHelper path =
  runIO (compileThatFile path) >>= liftData

这是该代码的简化版本,但希望能传达我的意思 正在努力。

注意 liftData 功能,它是 template-haskell-2.11 中的新功能,它承诺“提升”到 表达式 Data 的任何实例。非常酷,可以编译。

然而,当我这样使用它时:

main :: IO ()
main = do
  let compiled = $(myThHelper "/path/to/my/file/foo.txt")
  …

我从编译器收到以下错误消息:

• Can't find interface-file declaration for variable Data.Text.Internal.pack
    Probable cause: bug in .hi-boot file, or inconsistent .hi file
    Use -ddump-if-trace to get an idea of which file caused the error
• In the first argument of ‘PName’, namely
    ‘Data.Text.Internal.pack ((:) 'f' ((:) 'o' ((:) 'o' [])))’
  In the first argument of ‘Template’, namely
    ‘PName (Data.Text.Internal.pack ((:) 'f' ((:) 'o' ((:) 'o' []))))’
  In the expression:

等知道发生了什么以及如何解决它吗?


我通过实验确认,只有当要提升的数据类型包含 Text 时,问题才会出现。我要开个issue。


And here it is.

这好像是因为dataToQa expects the function that toConstr shows (which is "pack" for Text) to be in the same module the data type is defined. So liftData is looking for pack in Data.Text.Internal but pack is actually in Data.Text.

一个简单的修复方法是为 Text 编写自己的提升函数:

{-# LANGUAGE TemplateHaskell #-}

import qualified Data.Text as T
import Language.Haskell.TH.Syntax

liftText :: T.Text -> Q Exp
liftText txt = AppE (VarE 'T.pack) <$> lift (T.unpack txt)

myThHelper :: FilePath -> Q Exp
myThHelper path =
  runIO (compileThatFile path) >>= liftText

如果文本在您要使用的结构中很深,您可以使用 dataToExpQ,它可以让您针对特定类型的情况覆盖提升功能:

import Data.Data

liftDataWithText :: Data a => a -> Q Exp
liftDataWithText = dataToExpQ (\a -> liftText <$> cast a)