I'm trying to shift execution of some code to compile time with GHC 8 and
template-haskel-2.11
. The code looks like this:
myThHelper :: FilePath -> Q Exp
myThHelper path =
runIO (compileThatFile path) >>= liftData
This is a simplified version of that code but it hopefully conveys what I'm trying to do.
Note the
liftData
function, it's new in template-haskell-2.11
and it promises to “lift” into
expression any instance of Data
. Very cool and it compiles.
However, when I use it like so:
main :: IO ()
main = do
let compiled = $(myThHelper "/path/to/my/file/foo.txt")
…
I'm getting the following error message from the compiler:
• 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:
etc. Any idea what's going on and how to fix it?
I confirmed via experiments that the problem only manifests itself when data type to lift has Text
in it. I'm going to open an issue.
And here it is.
This seems to be because 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
.
An easy way to fix it is to just write your own lift function for 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
If text is deep in the structure you want to use, you can use dataToExpQ
which lets you override the lift function for type-specific cases:
import Data.Data
liftDataWithText :: Data a => a -> Q Exp
liftDataWithText = dataToExpQ (\a -> liftText <$> cast a)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With