Skip to content

Document workaround for TH name quoting restriction

Summary

The Template Haskell section of the GHC User's Guide states:

A name whose second character is a single quote (sadly) cannot be quoted in this way, because it will be parsed instead as a quoted character. For example, if the function is called f'7 (which is a legal Haskell identifier), an attempt to quote it as 'f'7 would be parsed as the character literal 'f' followed by the numeric literal 7. There is no current escape mechanism in this (unusual) situation.

Proposed improvements or changes

While there is no escape mechanism, per se, there is a workaround, and I think it should be described here. Define the following:

-- Unexported type
newtype Id a = Id {unId :: a}
  deriving (Functor, Applicative, Monad) via Identity
instance Quote Id where
  newName _ = withFrozenCallStack $ error extractNameError

extractName :: HasCallStack => Id Exp -> Name
extractName m = case unId m of
  VarE x -> x
  ConE x -> x
  _ -> withFrozenCallStack $ error extractNameError

extractNameError :: String
extractNameError = "extractName: the argument must be an expression quote containing a single bare name, such as [| f'1 |]"

If you have a function called f'7, you can effectively quote its name by writing

extractName [| f'7 |]

Perhaps there should be something like extractName in Language.Haskell.TH.Lib?

Environment

  • GHC version used (if appropriate):
Edited by David Feuer
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information