template-haskell中单双引号/撇号的区别是什么?



在使用Optics包学习Haskell镜头时,我遇到了以下示例:

data Person = Person 
{ _name :: String
, _age  :: Int
} 
makeLenses ''Person
makePrisms 'Person

类型为Name的值表示什么?该单引号/撇号与双引号/撇号的区别是什么?

两者似乎具有相同的类型:

makeLenses, makePrisms :: Name -> DecsQ

template-haskell文档对我来说是不可理解的。它侧重于语法,缺少示例:

* '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.

有两种形式的引用来区分数据构造函数和类型构造函数。

考虑这个变体:

data Person = KPerson 
{ _name :: String
, _age  :: Int
} 
makeLenses ''Person   -- the type constructor
makePrisms 'KPerson   -- the data constructor

这里很明显,在一种情况下,我们使用Name作为类型构造函数,而在另一种情况下,我们引用Name作为数据构造函数。

原则上,Haskell可以使用单一形式的引用,只要构造函数(如PersonKPerson)的名称始终保持不同。由于情况并非如此,我们需要消除命名类型和命名数据构造函数之间的歧义。

请注意,在实践中,习惯上对两个构造函数使用相同的名称,因此在实际代码中经常需要这种消歧。

类型构造函数和术语构造函数在Haskell中可以具有相同的名称,因此您可以分别使用双引号和单引号来表示差异。下面是光学中具有不同名称的例子:

data Person = P 
{ _name :: String
, _age  :: Int
} 
makeLenses ''Person
makePrisms 'P

相关内容

最新更新