I have a 'Month' type, which is roughly
newtype Month = Month Word8
where the Month
constructor isn't exported; instead, a function
mon :: Word8 -> Maybe Month
mon i = if i > 0 && i < 13
then Just $ Month i
else Nothing
is exported, which will only return a value if the input value is between 1 & 12 inclusive.
Now, using Language.Haskell.TH.Quote
, I have defined a quasi-quoting ... operator? ... that allows me to "create" instances of Month "at compile time":
month :: QuasiQuoter
month = QuasiQuoter { quoteDec = error "quoteDec not implemented"
, quoteType = error "quoteType not implemented"
, quotePat = "quotePat not implemented"
, quoteExp = (\ s → ⟦ force $ __fromString @Month s ⟧)
}
m :: Month
m = [month|3|]
Where __fromString
parses a string, and either returns a value or calls error
. force
is from Control.DeepSeq
.
Now this is well and good, but the principle value of this is to catch bad values as early as possible - but, thanks to Lazy Evaluation, the value m is not evaluated either at compile-time (which would be ideal, but a rather tall order, perhaps) or at least at the earliest stage of runtime.
Is there any way that I can annotate the value (preferably within the quasi-quotation infra, so that every use of month
gets it for free; but failing that, annotating m
) to force the evaluation of m
when the program gets run? Requiring an NFData
constraint or similar is fine.
Thanks,