在使用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可以使用单一形式的引用,只要构造函数(如Person
和KPerson
)的名称始终保持不同。由于情况并非如此,我们需要消除命名类型和命名数据构造函数之间的歧义。
请注意,在实践中,习惯上对两个构造函数使用相同的名称,因此在实际代码中经常需要这种消歧。
类型构造函数和术语构造函数在Haskell中可以具有相同的名称,因此您可以分别使用双引号和单引号来表示差异。下面是光学中具有不同名称的例子:
data Person = P
{ _name :: String
, _age :: Int
}
makeLenses ''Person
makePrisms 'P