2016-07-01 34 views
1

我试图转移一些代码的执行时间来编译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的情况下,问题才会显现。我打算开一个问题。


And here it is

回答

2

这似乎是因为dataToQa需要toConstr显示的功能(它是"pack"对于Text)位于数据类型定义的相同模块中。因此liftData正在寻找的Data.Text.Internal,但pack实际上是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) 
+0

我担心,“简单的方法”,将不适合我,因为我的数据有'Text'不是顶级,但在内心深处。 – Mark

+1

@Mark在这种情况下,您可以使用['dataToExQ'](http://hackage.haskell.org/package/template-haskell-2.11.0.0/docs/Language-Haskell-TH-Syntax.html#v:dataToExpQ )。我已经更新了我的答案。 – cchalmers

+0

现在很有趣。一旦我有时间,我会检查它,如果它有效,请接受你的答案。 – Mark