你写代码的方式,编译时不会进行评估。当你引用一个Haskell表达[| ... |]
,所报码/ AST插入您应用它没有任何评价,所以写:
$(hString "hello, world")
是完全一样的文字:
let s = "hello, world" in HashString (hash $ T.pack s) (T.pack s)
但认为它是这样的:你用[| ... |]
引用稍后插入的表达式,你产生在编译时有$(...)
代码。所以,如果你包括在引述表达bla = [| bar $(foo) |]
一些代码$(foo)
,做$(bla)
将生成的代码bar $(foo)
,这反过来将在编译时评估foo
。此外,拍摄您在编译时产生的值,并且从它的表达,可以使用lift
功能。所以,你想要做什么是这样的:
import Data.String (fromString)
import Language.Haskell.TH.Syntax
hString s = [| HashString $(lift . hash . T.pack $ s) (fromString s) |]
这种评估在编译时哈希函数,因为外部拼接得到解决后,内部拼接解决。顺便说一句,使用fromString
从Data.String
是从String
构建一些OverloadedString
数据类型的通用方法。
此外,你应该考虑做一个准报价者为您HashString
接口。采用准quoters比手动调用拼接功能更自然(你已经使用过;无名[| ... |]
加引号引用哈斯克尔表达式)。
您可以创建这样一个quasiquoter:
import Language.Haskell.TH.Quote
hstr =
QuasiQuoter
{ quoteExp = hString -- Convenient: You already have this function
, quotePat = undefined
, quoteType = undefined
, quoteDec = undefined
}
这将让你写HashString
s与这句法:
{-# LANGUAGE QuasiQuotes #-}
myHashString = [hstr|hello, world|]
出色答卷!谢谢。 – 2012-02-11 21:31:52