3

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

data Person = Person 
 { _name :: String
 , _age  :: Int
 } 

makeLenses ''Person
makePrisms 'Person

类型的值Name代表什么,单引号和双引号/撇号之间有什么区别?

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

makeLenses, makePrisms :: Name -> DecsQ

模板-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.

4

2 回答 2

3

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

考虑这个变体:

 data Person = KPerson 
    { _name :: String
    , _age  :: Int
    } 

makeLenses ''Person   -- the type constructor
makePrisms 'KPerson   -- the data constructor

很明显,在一种情况下,我们将 aName用于类型构造函数,而在另一种情况下,我们将 aName用于数据构造函数。

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

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

于 2021-09-26T08:17:05.707 回答
2

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

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

makeLenses ''Person
makePrisms 'P
于 2021-09-26T08:14:51.093 回答