あなたのコードを書いている途中、コンパイル時に評価は行われません。あなたは[| ... |]
で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) |]
これは、コンパイル時にハッシュ関数を評価します。ちなみにData.String
のfromString
を使用するのはString
のOverloadedString
データ型を構築する一般的な方法です。
また、HashString
インターフェイスの準引用符を作成することを検討する必要があります。準引用符を使用するのは、スプライス関数を手動で呼び出すよりも自然です(既に名前を使用していますが、無名の[| ... |]
引用符はHaskell式を引用しています)。
あなたはこのようquasiquoterを作成します。
import Language.Haskell.TH.Quote
hstr =
QuasiQuoter
{ quoteExp = hString -- Convenient: You already have this function
, quotePat = undefined
, quoteType = undefined
, quoteDec = undefined
}
これは、あなたがこの構文でHashString
の書いてみましょうになります。
{-# LANGUAGE QuasiQuotes #-}
myHashString = [hstr|hello, world|]
優秀な答えを!ありがとうございました。 –