{-# LANGUAGE DerivingVia #-}
module ExtractName (extractName) where
import Data.Functor.Identity
import GHC.Stack
import Language.Haskell.TH.Syntax
extractName :: HasCallStack => Id Exp -> Name
extractName m = case unId m of
VarE x -> x
ConE x -> x
_ -> withFrozenCallStack $ error extractNameError
newtype Id a = Id {unId :: a}
deriving (Functor, Applicative, Monad) via Identity
-- This is bogus, but good enough for what we're doing.
instance Quote Id where
newName _ = withFrozenCallStack $ error extractNameError
extractNameError :: String
extractNameError =
"extractName: the argument must be an expression quote containing a\n"
++ "single bare name, such as [| f'1 |]"
现在你可以写,例如,
f' :: Int
data Foo = B'ar
f'Name, b'arName :: Name
f'Name = extractName [| f' |]
b'arName = extractName [| B'ar |]
1条答案
按热度按时间ymdaylpp1#
编辑:看来用户指南关于没有转义机制的说法是错误的!你可以在最初的单引号后面加一个空格。所以......不要使用下面的方法。
可以使用表达式引用和伪
Quote
示例来解决此限制。现在你可以写,例如,
这是如何工作的?一个表达式引号将在实现
Quote
的任意单子中产生Exp
。一般来说,对表达式引号进行反糖化可能需要newName
方法,来对let
和lambda表达式进行反糖化。然而,它 * 不 * 需要newName
来对一个普通的旧绑定或数据构造函数进行反糖化。例如,一种类型,它可以用于我们需要的带引号的表达式。一旦我们打开表达式,我们就可以从中提取名称。