As you wrote your code, no evaluation will be performed at compile time. When you quote a Haskell expression with [| ... |] [| ... |] , the cited code / AST is inserted where you apply it without any evaluation, so write:
$(hString "hello, world")
exactly the same as the entry:
let s = "hello, world" in HashString (hash $ T.pack s) (T.pack s)
But think of it this way: you use [| ... |] [| ... |] to quote an expression to be inserted later, and you generate code at compile time with $(...) . So, if you included some $(foo) code in the quoted expression bla = [| bar $(foo) |] bla = [| bar $(foo) |] , then when $(bla) is executed, the code bar $(foo) will be generated, which, in turn, will evaluate foo at compile time. In addition, to get the value that you generate at compile time and generate an expression from it, you use the lift function. So what you want to do is the following:
import Data.String (fromString) import Language.Haskell.TH.Syntax hString s = [| HashString $(lift . hash . T.pack $ s) (fromString s) |]
This evaluates the hash function at compile time, since internal splicing is allowed after eliminating external splicing. By the way, using fromString from Data.String is a general way to build some OverloadedString data type from String .
In addition, you should consider creating a quasicycler for your HashString interface. Using quasicycles is more natural than manually calling splicing functions (and you already used them, an unnamed [| ... |] quoter quotes Haskell expressions).
You would create such a quasiquater:
import Language.Haskell.TH.Quote hstr = QuasiQuoter { quoteExp = hString -- Convenient: You already have this function , quotePat = undefined , quoteType = undefined , quoteDec = undefined }
This will allow you to write a HashString with this syntax:
{-# LANGUAGE QuasiQuotes #-} myHashString = [hstr|hello, world|]