コードを記述した方法では、コンパイル時に評価は行われません。Haskell式を。で引用すると[| ... |]
、引用されたコード/ ASTが評価なしで適用される場所に挿入されるため、次のように記述します。
$(hString "hello, world")
書くこととまったく同じです:
let s = "hello, world" in HashString (hash $ T.pack s) (T.pack s)
ただし、次のように考えてください。[| ... |]
後で挿入する式を引用するために使用し、コンパイル時に。を使用してコードを生成します$(...)
。$(foo)
したがって、引用符で囲まれた式bla = [| bar $(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
fromを使用することは、からいくつかのデータ型Data.String
を構築する一般的な方法です。OverloadedString
String
また、インターフェイスの準クォーターを作成することを検討する必要がありHashString
ます。準引用符を使用することは、スプライス関数を手動で呼び出すよりも自然です(そして、すでにそれらを使用しています。名前のない[| ... |]
引用符はHaskell式を引用します)。
次のような準クォーターを作成します。
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|]