模板-haskell中的单双引号/撇号有啥区别?
Posted
技术标签:
【中文标题】模板-haskell中的单双引号/撇号有啥区别?【英文标题】:What is the difference between single double qoute/apostrophe in template-haskell?模板-haskell中的单双引号/撇号有什么区别? 【发布时间】:2021-11-18 19:05:56 【问题描述】:在使用 Optics 包了解 Haskell 镜头时,我遇到了以下示例:
data Person = Person
_name :: String
, _age :: Int
makeLenses ''Person
makePrisms 'Person
Name
类型的值代表什么?单引号和双引号之间有什么区别?
两者似乎具有相同的类型:
makeLenses, makePrisms :: Name -> DecsQ
template-haskell documentation 对我来说是不可理解的。侧重于语法,缺乏示例:
* 'f has type Name, and names the function f. Similarly 'C has type Name and names the data constructor C. In general '⟨thing⟩ interprets ⟨thing⟩ in an expression context.
* ''T has type Name, and names the type constructor T. That is, ''⟨thing⟩ interprets ⟨thing⟩ in a type context.
【问题讨论】:
【参考方案1】:我们有两种引用形式来区分数据构造函数和类型构造函数。
考虑这个变体:
data Person = KPerson
_name :: String
, _age :: Int
makeLenses ''Person -- the type constructor
makePrisms 'KPerson -- the data constructor
很明显,在一种情况下,我们使用Name
作为类型构造函数,而在另一种情况下,我们使用Name
作为数据构造函数。
原则上,Haskell 可以使用单一形式的引用,前提是 Person
和 KPerson
等构造函数的名称始终保持不同。由于情况并非如此,我们需要在命名类型和数据构造函数之间消除歧义。
请注意,在实践中,习惯上为两个构造函数使用相同的名称,因此在实际代码中经常需要这种消歧。
【讨论】:
谢谢。我现在将引号理解为独特地创建类型和值构造函数的元表示。但是,我仍然不明白为什么我可以互换地传递类型和值名称:makeLenses ''Person
和 makeLenses 'KPerson
似乎都可以工作。
@manews 这是一个很好的观点。在内部,我可以从源代码中看到makeLenses
调用reifyDatatype
,其文档声明“此函数将接受使用 newtype 或 data 声明的类型的任何构造函数(值或类型)”。所以我想这使得两者都起作用。 hackage.haskell.org/package/th-abstraction-0.4.3.0/docs/… 看起来这样做是为了使 数据系列 工作——不是常见的情况。【参考方案2】:
类型构造函数和术语构造函数在 Haskell 中可以具有相同的名称,因此您可以分别使用双引号和单引号来表示区别。这是光学中具有不同名称的示例:
data Person = P
_name :: String
, _age :: Int
makeLenses ''Person
makePrisms 'P
【讨论】:
以上是关于模板-haskell中的单双引号/撇号有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章