Il modo in cui hai scritto il codice, nessuna valutazione avverrà in fase di compilazione. Quando si cita un'espressione Haskell con [| ... |]
, il codice/AST citato è inserita in cui lo si applica, senza alcuna valutazione, in modo da scrivere:
$(hString "hello, world")
è esattamente lo stesso di scrittura:
let s = "hello, world" in HashString (hash $ T.pack s) (T.pack s)
Ma pensa su di esso in questo modo: si utilizza [| ... |]
per citare un'espressione da inserire in seguito e si genera codice in fase di compilazione con $(...)
. Quindi, se includi del codice $(foo)
in un'espressione quotata bla = [| bar $(foo) |]
, facendo $(bla)
verrà generato il codice bar $(foo)
, che a sua volta valuterà foo
in fase di compilazione. Inoltre, per prendere un valore generato in fase di compilazione e generare un'espressione da esso, si utilizza la funzione lift
. Quindi, ciò che si vuole fare è questo:
import Data.String (fromString)
import Language.Haskell.TH.Syntax
hString s = [| HashString $(lift . hash . T.pack $ s) (fromString s) |]
Questa valuta la funzione di hash al momento della compilazione, dal momento che la giunzione interna viene risolto dopo il giunto esterno è stato risolto. A proposito, usareda Data.String
è il modo generico di costruire un certo tipo di dati OverloadedString
da un String
.
Inoltre, si dovrebbe prendere in considerazione l'idea di fare un quasi-quoter per l'interfaccia HashString
. L'uso di quasi-quoter è più naturale di quello che si chiama manualmente le funzioni di splicing (e le hai già usate, il citofono senza nome [| ... |]
cita le espressioni di Haskell).
Si potrebbe creare un quasiquoter come questo:
import Language.Haskell.TH.Quote
hstr =
QuasiQuoter
{ quoteExp = hString -- Convenient: You already have this function
, quotePat = undefined
, quoteType = undefined
, quoteDec = undefined
}
Questo avrebbe permesso che si scrive HashString
s con la seguente sintassi:
{-# LANGUAGE QuasiQuotes #-}
myHashString = [hstr|hello, world|]
Ottima risposta! Grazie. –