Template Haskell中单引号与双单引号的区别及Name类型的含义是什么?
相关概念解释
1. Name 类型的含义
Name 是 Haskell Template Haskell 扩展中定义的基础类型,作用是唯一标识一个Haskell语法实体,这些实体可以是类型构造器、数据构造器、函数、类型类等。你可以把它理解为对应语法元素的全局唯一标识符,内部存储了实体的名称、所属模块、作用域等信息,makeLenses、makePrisms这类代码生成函数需要拿到这个标识符,才能明确要针对哪个结构生成对应的光学子代码。
2. 单撇(')和双撇('')前缀的区别
二者都是Template Haskell提供的「获取实体Name」的语法,核心区别是查找实体的上下文不同:
- 单撇前缀
':在值/表达式上下文中查找实体,返回的是值层面实体的Name,比如普通函数、数据构造器这类运行时会存在的实体。 - 双撇前缀
'':在类型上下文中查找实体,返回的是类型层面实体的Name,比如类型构造器、类型类这类类型检查阶段会用到的实体。
3. 结合示例代码的具体说明
你给出的定义:
data Person = Person { _name :: String , _age :: Int }
里存在两个同名的Person实体,刚好对应两种不同的上下文:
- 类型层面的类型构造器
Person:用来表示Person这个数据类型本身,属于类型上下文的实体,所以用双撇获取它的Name,也就是''Person。 - 值层面的数据构造器
Person:用来构造Person类型的具体值,属于值上下文的实体,所以用单撇获取它的Name,也就是'Person。
两个函数参数类型均为Name -> DecsQ的原因是,Name本身没有在类型上区分实体所属的层面,函数会在编译期内部校验传入的Name对应的实体是否符合要求:
makeLenses需要针对整个数据类型的所有字段生成lens,所以要求传入类型构造器的Name,也就是你示例中的''Person。makePrisms需要针对数据构造器生成对应的prism,所以要求传入数据构造器的Name,也就是你示例中的'Person。
如果传错了实体类型,编译阶段会直接抛出明确的错误提示。
内容的提问来源于stack exchange,提问作者manews
相关产品推荐
相关产品推荐

